diff --git a/.gitignore b/.gitignore index b1062f172..80fbc3543 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,9 @@ junit.xml .saddle_history contracts/generated +# Claude-generated summaries +.claude-docs/ + # yarn .yarn/* !.yarn/patches diff --git a/contracts/Comptroller/ComptrollerInterface.sol b/contracts/Comptroller/ComptrollerInterface.sol index 532aba846..910e0b6a6 100644 --- a/contracts/Comptroller/ComptrollerInterface.sol +++ b/contracts/Comptroller/ComptrollerInterface.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.25; import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; +import { IDeviationBoundedOracle } from "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol"; import { VToken } from "../Tokens/VTokens/VToken.sol"; import { VAIControllerInterface } from "../Tokens/VAI/VAIControllerInterface.sol"; @@ -132,6 +133,8 @@ interface ComptrollerInterface { function oracle() external view returns (ResilientOracleInterface); + function deviationBoundedOracle() external view returns (IDeviationBoundedOracle); + function getAccountLiquidity(address) external view returns (uint, uint, uint); function getAssetsIn(address) external view returns (VToken[] memory); diff --git a/contracts/Comptroller/ComptrollerStorage.sol b/contracts/Comptroller/ComptrollerStorage.sol index b732430b8..baacede36 100644 --- a/contracts/Comptroller/ComptrollerStorage.sol +++ b/contracts/Comptroller/ComptrollerStorage.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.25; import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; +import { IDeviationBoundedOracle } from "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol"; import { PoolMarketId } from "./Types/PoolMarketId.sol"; import { VToken } from "../Tokens/VTokens/VToken.sol"; @@ -328,3 +329,8 @@ contract ComptrollerV18Storage is ComptrollerV17Storage { /// @notice Whether flash loans are paused system-wide bool public flashLoanPaused; } + +contract ComptrollerV19Storage is ComptrollerV18Storage { + /// @notice DeviationBoundedOracle for conservative pricing in CF path + IDeviationBoundedOracle public deviationBoundedOracle; +} diff --git a/contracts/Comptroller/Diamond/Diamond.sol b/contracts/Comptroller/Diamond/Diamond.sol index 82fb511af..d50e96e8e 100644 --- a/contracts/Comptroller/Diamond/Diamond.sol +++ b/contracts/Comptroller/Diamond/Diamond.sol @@ -4,14 +4,14 @@ pragma solidity 0.8.25; import { IDiamondCut } from "./interfaces/IDiamondCut.sol"; import { Unitroller } from "../Unitroller.sol"; -import { ComptrollerV18Storage } from "../ComptrollerStorage.sol"; +import { ComptrollerV19Storage } from "../ComptrollerStorage.sol"; /** * @title Diamond * @author Venus * @notice This contract contains functions related to facets */ -contract Diamond is IDiamondCut, ComptrollerV18Storage { +contract Diamond is IDiamondCut, ComptrollerV19Storage { /// @notice Emitted when functions are added, replaced or removed to facets event DiamondCut(IDiamondCut.FacetCut[] _diamondCut); @@ -72,7 +72,7 @@ contract Diamond is IDiamondCut, ComptrollerV18Storage { */ function facetAddress( bytes4 functionSelector - ) external view returns (ComptrollerV18Storage.FacetAddressAndPosition memory) { + ) external view returns (ComptrollerV19Storage.FacetAddressAndPosition memory) { return _selectorToFacetAndPosition[functionSelector]; } diff --git a/contracts/Comptroller/Diamond/facets/FacetBase.sol b/contracts/Comptroller/Diamond/facets/FacetBase.sol index e7caa62cf..b3f51dff0 100644 --- a/contracts/Comptroller/Diamond/facets/FacetBase.sol +++ b/contracts/Comptroller/Diamond/facets/FacetBase.sol @@ -10,7 +10,8 @@ import { VToken } from "../../../Tokens/VTokens/VToken.sol"; import { ComptrollerErrorReporter } from "../../../Utils/ErrorReporter.sol"; import { ExponentialNoError } from "../../../Utils/ExponentialNoError.sol"; import { IVAIVault, Action } from "../../../Comptroller/ComptrollerInterface.sol"; -import { ComptrollerV18Storage } from "../../../Comptroller/ComptrollerStorage.sol"; +import { ComptrollerV19Storage } from "../../../Comptroller/ComptrollerStorage.sol"; +import { IDeviationBoundedOracle } from "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol"; import { PoolMarketId } from "../../../Comptroller/Types/PoolMarketId.sol"; import { IFacetBase, WeightFunction } from "../interfaces/IFacetBase.sol"; @@ -19,7 +20,7 @@ import { IFacetBase, WeightFunction } from "../interfaces/IFacetBase.sol"; * @author Venus * @notice This facet contract contains functions related to access and checks */ -contract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter { +contract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter { using SafeERC20 for IERC20; /// @notice The initial Venus index for a market @@ -134,19 +135,19 @@ contract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, Com } /** - * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed - * @param vTokenModify The market to hypothetically redeem/borrow in + * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts. + * Use this in state-changing contexts (hooks, claim flows, pool selection). + * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before + * delegating to the lens, which updates the bounded price and enables protection if the deviation + * exceeds the threshold. * @param account The account to determine liquidity for - * @param redeemTokens The number of tokens to hypothetically redeem + * @param vTokenModify The market to hypothetically redeem/borrow in + * @param redeemTokens The number of vTokens to hypothetically redeem * @param borrowAmount The amount of underlying to hypothetically borrow - * @param weightingStrategy The weighting strategy to use: - * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold - * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data, - * without calculating accumulated interest. - * @return (possible error code, - hypothetical account liquidity in excess of collateral requirements, - * hypothetical account shortfall below collateral requirements) + * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks + * @return err Possible error code + * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall) + * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent) */ function getHypotheticalAccountLiquidityInternal( address account, @@ -154,6 +155,49 @@ contract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, Com uint256 redeemTokens, uint256 borrowAmount, WeightFunction weightingStrategy + ) internal returns (Error, uint256, uint256) { + // Populate the DBO transient price cache (EIP-1153) for all entered assets. + // Required on the CF path so bounded prices are computed once and reused + // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView) + // within the same transaction. + if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) { + _updateProtectionStates(account); + } + (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity( + address(this), + account, + vTokenModify, + redeemTokens, + borrowAmount, + weightingStrategy + ); + return (Error(err), liquidity, shortfall); + } + + /** + * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating + * the transient cache. Use this only in external view functions where state mutation is not + * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead. + * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`) + * was already executed earlier in the same transaction, the DBO transient cache will already be + * populated and this function will read from it gas-efficiently — no recomputation occurs. + * If called in a standalone view context (cold cache), the DBO must compute bounded prices from + * scratch on each call; results are still correct but cost more gas. + * @param account The account to determine liquidity for + * @param vTokenModify The market to hypothetically redeem/borrow in + * @param redeemTokens The number of vTokens to hypothetically redeem + * @param borrowAmount The amount of underlying to hypothetically borrow + * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks + * @return err Possible error code + * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall) + * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent) + */ + function getHypotheticalAccountLiquidityInternalView( + address account, + VToken vTokenModify, + uint256 redeemTokens, + uint256 borrowAmount, + WeightFunction weightingStrategy ) internal view returns (Error, uint256, uint256) { (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity( address(this), @@ -200,11 +244,7 @@ contract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, Com * @param redeemTokens Amount of tokens to redeem * @return Success indicator for redeem is allowed or not */ - function redeemAllowedInternal( - address vToken, - address redeemer, - uint256 redeemTokens - ) internal view returns (uint256) { + function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) { ensureListed(getCorePoolMarket(vToken)); /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */ if (!getCorePoolMarket(vToken).accountMembership[redeemer]) { @@ -260,27 +300,17 @@ contract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, Com } /** - * @notice Determine the current account liquidity wrt collateral requirements - * @param account The account to get liquidity for - * @param weightingStrategy The weighting strategy to use: - * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold - * @return (possible error code (semi-opaque), - * account liquidity in excess of collateral requirements, - * account shortfall below collateral requirements) + * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered + * @dev This populates the transient price cache so subsequent view calls in the same transaction + * are gas-efficient. Should be called before any liquidity calculation in the CF path. + * @param account The account whose collateral assets need protection state updates */ - function _getAccountLiquidity( - address account, - WeightFunction weightingStrategy - ) internal view returns (uint256, uint256, uint256) { - (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal( - account, - VToken(address(0)), - 0, - 0, - weightingStrategy - ); - - return (uint256(err), liquidity, shortfall); + function _updateProtectionStates(address account) internal { + IDeviationBoundedOracle boundedOracle = deviationBoundedOracle; + VToken[] memory assets = accountAssets[account]; + uint256 len = assets.length; + for (uint256 i; i < len; ++i) { + boundedOracle.updateProtectionState(address(assets[i])); + } } } diff --git a/contracts/Comptroller/Diamond/facets/MarketFacet.sol b/contracts/Comptroller/Diamond/facets/MarketFacet.sol index b690e35f1..5261cd9b2 100644 --- a/contracts/Comptroller/Diamond/facets/MarketFacet.sol +++ b/contracts/Comptroller/Diamond/facets/MarketFacet.sol @@ -359,10 +359,15 @@ contract MarketFacet is IMarketFacet, FacetBase { userPoolId[msg.sender] = poolId; - (uint256 error, , uint256 shortfall) = _getAccountLiquidity(msg.sender, WeightFunction.USE_COLLATERAL_FACTOR); - - if (error != 0 || shortfall > 0) { - revert LiquidityCheckFailed(error, shortfall); + (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal( + msg.sender, + VToken(address(0)), + 0, + 0, + WeightFunction.USE_COLLATERAL_FACTOR + ); + if (err != Error.NO_ERROR || shortfall > 0) { + revert LiquidityCheckFailed(uint256(err), shortfall); } } diff --git a/contracts/Comptroller/Diamond/facets/PolicyFacet.sol b/contracts/Comptroller/Diamond/facets/PolicyFacet.sol index 32f831e86..f1c5cac86 100644 --- a/contracts/Comptroller/Diamond/facets/PolicyFacet.sol +++ b/contracts/Comptroller/Diamond/facets/PolicyFacet.sol @@ -130,7 +130,8 @@ contract PolicyFacet is IPolicyFacet, XVSRewardsHelper { } } - if (oracle.getUnderlyingPrice(vToken) == 0) { + (uint256 collateralPrice, uint256 debtPrice) = deviationBoundedOracle.getBoundedPricesView(vToken); + if (collateralPrice == 0 || debtPrice == 0) { return uint256(Error.PRICE_ERROR); } @@ -258,7 +259,7 @@ contract PolicyFacet is IPolicyFacet, XVSRewardsHelper { } /* The borrower must have shortfall in order to be liquidatable */ - (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal( + (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternalView( borrower, VToken(address(0)), 0, @@ -426,7 +427,14 @@ contract PolicyFacet is IPolicyFacet, XVSRewardsHelper { * account shortfall below collateral requirements) */ function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) { - return _getAccountLiquidity(account, WeightFunction.USE_COLLATERAL_FACTOR); + (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView( + account, + VToken(address(0)), + 0, + 0, + WeightFunction.USE_COLLATERAL_FACTOR + ); + return (uint256(err), liquidity, shortfall); } /** @@ -437,7 +445,14 @@ contract PolicyFacet is IPolicyFacet, XVSRewardsHelper { * account shortfall below liquidation threshold requirements) */ function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) { - return _getAccountLiquidity(account, WeightFunction.USE_LIQUIDATION_THRESHOLD); + (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView( + account, + VToken(address(0)), + 0, + 0, + WeightFunction.USE_LIQUIDATION_THRESHOLD + ); + return (uint256(err), liquidity, shortfall); } /** @@ -456,7 +471,7 @@ contract PolicyFacet is IPolicyFacet, XVSRewardsHelper { uint256 redeemTokens, uint256 borrowAmount ) external view returns (uint256, uint256, uint256) { - (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal( + (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView( account, VToken(vTokenModify), redeemTokens, diff --git a/contracts/Comptroller/Diamond/facets/RewardFacet.sol b/contracts/Comptroller/Diamond/facets/RewardFacet.sol index c61043e38..7de3ac58c 100644 --- a/contracts/Comptroller/Diamond/facets/RewardFacet.sol +++ b/contracts/Comptroller/Diamond/facets/RewardFacet.sol @@ -169,6 +169,10 @@ contract RewardFacet is IRewardFacet, XVSRewardsHelper { /** * @notice Claim all xvs accrued by the holders + * @dev The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices. + * When DBO protection mode is active, a holder with a position that is healthy at spot prices may still + * show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when + * `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO. * @param holders The addresses to claim XVS for * @param vTokens The list of markets to claim XVS in * @param borrowers Whether or not to claim XVS earned by borrowing diff --git a/contracts/Comptroller/Diamond/facets/SetterFacet.sol b/contracts/Comptroller/Diamond/facets/SetterFacet.sol index 61c098820..110efe673 100644 --- a/contracts/Comptroller/Diamond/facets/SetterFacet.sol +++ b/contracts/Comptroller/Diamond/facets/SetterFacet.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.25; import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; +import { IDeviationBoundedOracle } from "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol"; import { VToken } from "../../../Tokens/VTokens/VToken.sol"; import { Action } from "../../ComptrollerInterface.sol"; @@ -42,6 +43,12 @@ contract SetterFacet is ISetterFacet, FacetBase { /// @notice Emitted when price oracle is changed event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle); + /// @notice Emitted when deviation bounded oracle is changed + event NewDeviationBoundedOracle( + IDeviationBoundedOracle oldDeviationBoundedOracle, + IDeviationBoundedOracle newDeviationBoundedOracle + ); + /// @notice Emitted when borrow cap for a vToken is changed event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap); @@ -764,6 +771,26 @@ contract SetterFacet is ISetterFacet, FacetBase { m.isBorrowAllowed = borrowAllowed; } + /** + * @notice Sets the DeviationBoundedOracle for conservative CF-path pricing + * @param newDeviationBoundedOracle The new DeviationBoundedOracle contract + * @return uint256 0=success, otherwise a failure + */ + function setDeviationBoundedOracle( + IDeviationBoundedOracle newDeviationBoundedOracle + ) external compareAddress(address(deviationBoundedOracle), address(newDeviationBoundedOracle)) returns (uint256) { + ensureAllowed("setDeviationBoundedOracle(address)"); + + ensureNonzeroAddress(address(newDeviationBoundedOracle)); + + IDeviationBoundedOracle oldDeviationBoundedOracle = deviationBoundedOracle; + deviationBoundedOracle = newDeviationBoundedOracle; + + emit NewDeviationBoundedOracle(oldDeviationBoundedOracle, newDeviationBoundedOracle); + + return uint256(Error.NO_ERROR); + } + /** * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle * @param newOracle The new price oracle to be set diff --git a/contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol b/contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol index ad5df00e0..8e6f77fc8 100644 --- a/contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol +++ b/contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol @@ -3,10 +3,8 @@ pragma solidity 0.8.25; import { VToken } from "../../../Tokens/VTokens/VToken.sol"; -import { Action } from "../../ComptrollerInterface.sol"; -import { IFacetBase } from "./IFacetBase.sol"; -interface IRewardFacet is IFacetBase { +interface IRewardFacet { function claimVenus(address holder) external; function claimVenus(address holder, VToken[] calldata vTokens) external; diff --git a/contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol b/contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol index 9bd0bbe9b..13ac4da58 100644 --- a/contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol +++ b/contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol @@ -3,6 +3,7 @@ pragma solidity 0.8.25; import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; +import { IDeviationBoundedOracle } from "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol"; import { VToken } from "../../../Tokens/VTokens/VToken.sol"; import { Action } from "../../ComptrollerInterface.sol"; import { VAIControllerInterface } from "../../../Tokens/VAI/VAIControllerInterface.sol"; @@ -105,4 +106,6 @@ interface ISetterFacet { function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external; function setFlashLoanPaused(bool paused) external; + + function setDeviationBoundedOracle(IDeviationBoundedOracle newDeviationBoundedOracle) external returns (uint256); } diff --git a/contracts/Lens/ComptrollerLens.sol b/contracts/Lens/ComptrollerLens.sol index 4fb27a903..acca3c503 100644 --- a/contracts/Lens/ComptrollerLens.sol +++ b/contracts/Lens/ComptrollerLens.sol @@ -5,9 +5,11 @@ pragma solidity 0.8.25; import { VToken } from "../Tokens/VTokens/VToken.sol"; import { ExponentialNoError } from "../Utils/ExponentialNoError.sol"; import { ComptrollerErrorReporter } from "../Utils/ErrorReporter.sol"; +import { ResilientOracleInterface } from "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol"; import { ComptrollerInterface } from "../Comptroller/ComptrollerInterface.sol"; import { ComptrollerLensInterface } from "../Comptroller/ComptrollerLensInterface.sol"; import { VAIControllerInterface } from "../Tokens/VAI/VAIControllerInterface.sol"; +import { IDeviationBoundedOracle } from "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol"; import { WeightFunction } from "../Comptroller/Diamond/interfaces/IFacetBase.sol"; /** @@ -31,8 +33,11 @@ contract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, uint oraclePriceMantissa; Exp weightedFactor; Exp exchangeRate; - Exp oraclePrice; Exp tokensToDenom; + Exp collateralPrice; + Exp debtPrice; + IDeviationBoundedOracle boundedOracle; + ResilientOracleInterface spotOracle; } /** @@ -203,17 +208,22 @@ contract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, } /** - * @notice Internal function to calculate account position - * @param comptroller Address of comptroller - * @param account Address of the account whose liquidity is being calculated - * @param vTokenModify The vToken being modified (redeemed or borrowed) - * @param redeemTokens Number of vTokens being redeemed - * @param borrowAmount Amount borrowed - * @param weightingStrategy The weighting strategy to use: - * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold - * @return oErr Returns an error code indicating success or failure - * @return vars Returns an AccountLiquidityLocalVars struct containing the calculated values + * @notice Computes an account's aggregate weighted-collateral and total-borrow values, + * optionally applying hypothetical redeem/borrow effects on a single market. + * @dev Pricing differs by weighting strategy: + * - USE_COLLATERAL_FACTOR: collateral is valued at `DeviationBoundedOracle.getBoundedCollateralPriceView`, + * borrows at `getBoundedDebtPriceView`. + * - USE_LIQUIDATION_THRESHOLD: both collateral and borrows use the spot oracle price. + * VAI borrows (from `vaiController.getVAIRepayAmount`) are added to `sumBorrowPlusEffects` after + * the per-asset loop, regardless of weighting strategy. + * @param comptroller Address of the comptroller whose markets and oracle are used + * @param account Address of the account whose position is being computed + * @param vTokenModify Market to apply hypothetical effects on; pass `VToken(address(0))` for none + * @param redeemTokens Number of vTokens hypothetically redeemed from `vTokenModify` + * @param borrowAmount Amount of underlying hypothetically borrowed from `vTokenModify` + * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks + * @return oErr 0 on success, or a non-zero `Error` code (SNAPSHOT_ERROR or PRICE_ERROR) on failure + * @return vars Accumulated position data; `sumCollateral` and `sumBorrowPlusEffects` are the primary outputs */ function _calculateAccountPosition( address comptroller, @@ -226,6 +236,11 @@ contract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, // For each asset the account is in VToken[] memory assets = ComptrollerInterface(comptroller).getAssetsIn(account); uint assetsCount = assets.length; + if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) { + vars.boundedOracle = ComptrollerInterface(comptroller).deviationBoundedOracle(); + } else { + vars.spotOracle = ComptrollerInterface(comptroller).oracle(); + } for (uint i = 0; i < assetsCount; ++i) { VToken asset = assets[i]; @@ -246,40 +261,51 @@ contract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, }); vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa }); - // Get the normalized price of the asset - vars.oraclePriceMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(address(asset)); - if (vars.oraclePriceMantissa == 0) { - return (uint(Error.PRICE_ERROR), vars); + // Determine bounded prices for CF path + if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) { + (uint256 collateralPriceMantissa, uint256 debtPriceMantissa) = vars.boundedOracle.getBoundedPricesView( + address(asset) + ); + if (collateralPriceMantissa == 0 || debtPriceMantissa == 0) { + return (uint(Error.PRICE_ERROR), vars); + } + vars.collateralPrice = Exp({ mantissa: collateralPriceMantissa }); + vars.debtPrice = Exp({ mantissa: debtPriceMantissa }); + } else { + // LT path — always spot + vars.oraclePriceMantissa = vars.spotOracle.getUnderlyingPrice(address(asset)); + if (vars.oraclePriceMantissa == 0) { + return (uint(Error.PRICE_ERROR), vars); + } + vars.collateralPrice = Exp({ mantissa: vars.oraclePriceMantissa }); + vars.debtPrice = Exp({ mantissa: vars.oraclePriceMantissa }); } - vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa }); // Pre-compute a conversion factor from tokens -> bnb (normalized price value) - vars.tokensToDenom = mul_(mul_(vars.weightedFactor, vars.exchangeRate), vars.oraclePrice); + vars.tokensToDenom = mul_(mul_(vars.weightedFactor, vars.exchangeRate), vars.collateralPrice); // sumCollateral += tokensToDenom * vTokenBalance vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.vTokenBalance, vars.sumCollateral); - // sumBorrowPlusEffects += oraclePrice * borrowBalance + // sumBorrowPlusEffects += debtPrice * borrowBalance vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt( - vars.oraclePrice, + vars.debtPrice, vars.borrowBalance, vars.sumBorrowPlusEffects ); // Calculate effects of interacting with vTokenModify if (asset == vTokenModify) { - // redeem effect - // sumBorrowPlusEffects += tokensToDenom * redeemTokens + // redeem effect — uses collateral-bounded tokensToDenom vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt( vars.tokensToDenom, redeemTokens, vars.sumBorrowPlusEffects ); - // borrow effect - // sumBorrowPlusEffects += oraclePrice * borrowAmount + // borrow effect — uses debt-bounded price vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt( - vars.oraclePrice, + vars.debtPrice, borrowAmount, vars.sumBorrowPlusEffects ); diff --git a/contracts/Lens/SnapshotLens.sol b/contracts/Lens/SnapshotLens.sol index f24a6aae7..528ae8fe5 100644 --- a/contracts/Lens/SnapshotLens.sol +++ b/contracts/Lens/SnapshotLens.sol @@ -9,6 +9,7 @@ import { ExponentialNoError } from "../Utils/ExponentialNoError.sol"; import { ComptrollerInterface } from "../Comptroller/ComptrollerInterface.sol"; import { VBep20 } from "../Tokens/VTokens/VBep20.sol"; import { WeightFunction } from "../Comptroller/Diamond/interfaces/IFacetBase.sol"; +import { IDeviationBoundedOracle } from "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol"; contract SnapshotLens is ExponentialNoError { struct AccountSnapshot { @@ -21,7 +22,9 @@ contract SnapshotLens is ExponentialNoError { uint256 collateral; uint256 borrows; uint256 borrowsInUsd; - uint256 assetPrice; + uint256 spotPrice; + uint256 boundedCollateralPrice; + uint256 boundedDebtPrice; uint256 accruedInterest; uint vTokenDecimals; uint underlyingDecimals; @@ -95,22 +98,30 @@ contract SnapshotLens is ExponentialNoError { ); vars.collateralFactor = Exp({ mantissa: collateralFactorMantissa }); - // Get the normalized price of the asset + // Get the normalized spot price of the asset vars.oraclePriceMantissa = ComptrollerInterface(comptrollerAddress).oracle().getUnderlyingPrice( address(vToken) ); vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa }); - // Pre-compute a conversion factor from tokens -> bnb (normalized price value) - vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice); + // Get bounded prices from DBO (used in CF-path liquidity calculations) + IDeviationBoundedOracle boundedOracle = ComptrollerInterface(comptrollerAddress).deviationBoundedOracle(); + (uint256 boundedCollateralPriceMantissa, uint256 boundedDebtPriceMantissa) = boundedOracle.getBoundedPricesView( + address(vToken) + ); - //Collateral = tokensToDenom * vTokenBalance + // Collateral uses bounded collateral price (mirrors ComptrollerLens CF path) + Exp memory collateralPrice = Exp({ mantissa: boundedCollateralPriceMantissa }); + vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), collateralPrice); vars.collateral = mul_ScalarTruncate(vars.tokensToDenom, vars.vTokenBalance); + // Supply in USD uses spot price (real market value of supplied assets) vars.balanceOfUnderlying = vToken.balanceOfUnderlying(account); vars.supplyInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.balanceOfUnderlying); - vars.borrowsInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.borrowBalance); + // Borrows in USD uses bounded debt price (mirrors ComptrollerLens CF path) + Exp memory debtPrice = Exp({ mantissa: boundedDebtPriceMantissa }); + vars.borrowsInUsd = mul_ScalarTruncate(debtPrice, vars.borrowBalance); address underlyingAssetAddress; uint underlyingDecimals; @@ -137,7 +148,9 @@ contract SnapshotLens is ExponentialNoError { collateral: vars.collateral, borrows: vars.borrowBalance, borrowsInUsd: vars.borrowsInUsd, - assetPrice: vars.oraclePriceMantissa, + spotPrice: vars.oraclePriceMantissa, + boundedCollateralPrice: boundedCollateralPriceMantissa, + boundedDebtPrice: boundedDebtPriceMantissa, accruedInterest: vToken.borrowIndex(), vTokenDecimals: vToken.decimals(), underlyingDecimals: underlyingDecimals, diff --git a/contracts/Tokens/VAI/VAIController.sol b/contracts/Tokens/VAI/VAIController.sol index 3570d3d1b..d8675b5a6 100644 --- a/contracts/Tokens/VAI/VAIController.sol +++ b/contracts/Tokens/VAI/VAIController.sol @@ -13,6 +13,7 @@ import { IVAI } from "./IVAI.sol"; import { IPrime } from "../Prime/IPrime.sol"; import { VTokenInterface } from "../VTokens/VTokenInterfaces.sol"; import { VAIControllerStorageG4 } from "./VAIControllerStorage.sol"; +import { IDeviationBoundedOracle } from "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol"; /** * @title VAI Comptroller @@ -123,6 +124,8 @@ contract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAICon uint256 vaiNewTotalSupply = add_(vaiTotalSupply, mintVAIAmount); require(vaiNewTotalSupply <= mintCap, "mint cap reached"); + _updateProtectionStateForEnteredMarkets(minter); + uint256 accountMintableVAI; (err, accountMintableVAI) = getMintableVAI(minter); require(err == uint256(Error.NO_ERROR), "could not compute mintable amount"); @@ -438,9 +441,11 @@ contract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAICon uint256 vTokenBalance; uint256 borrowBalance; uint256 exchangeRateMantissa; - uint256 oraclePriceMantissa; + uint256 collateralPriceMantissa; + uint256 debtPriceMantissa; Exp exchangeRate; - Exp oraclePrice; + Exp collateralPrice; + Exp debtPrice; Exp tokensToDenom; } @@ -457,8 +462,8 @@ contract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAICon return (uint256(Error.REJECTION), 0); } - ResilientOracleInterface oracle = comptroller.oracle(); VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter); + IDeviationBoundedOracle boundedOracle = comptroller.deviationBoundedOracle(); AccountAmountLocalVars memory vars; // Holds all our calculation results @@ -479,14 +484,17 @@ contract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAICon } vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa }); - // Get the normalized price of the asset - vars.oraclePriceMantissa = oracle.getUnderlyingPrice(address(enteredMarkets[i])); - if (vars.oraclePriceMantissa == 0) { + // Get bounded prices: collateral price for supply valuation, debt price for borrow valuation + (vars.collateralPriceMantissa, vars.debtPriceMantissa) = boundedOracle.getBoundedPricesView( + address(enteredMarkets[i]) + ); + if (vars.collateralPriceMantissa == 0 || vars.debtPriceMantissa == 0) { return (uint256(Error.PRICE_ERROR), 0); } - vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa }); + vars.collateralPrice = Exp({ mantissa: vars.collateralPriceMantissa }); + vars.debtPrice = Exp({ mantissa: vars.debtPriceMantissa }); - (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.oraclePrice); + (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.collateralPrice); if (vars.mErr != MathError.NO_ERROR) { return (uint256(Error.MATH_ERROR), 0); } @@ -513,9 +521,9 @@ contract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAICon return (uint256(Error.MATH_ERROR), 0); } - // sumBorrowPlusEffects += oraclePrice * borrowBalance + // sumBorrowPlusEffects += debtPrice * borrowBalance (vars.mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt( - vars.oraclePrice, + vars.debtPrice, vars.borrowBalance, vars.sumBorrowPlusEffects ); @@ -878,4 +886,16 @@ contract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAICon function _ensureNonzeroAmount(uint256 amount) private pure { require(amount > 0, "amount can't be zero"); } + + /// @dev Persists the DBO protection window for every market the minter has entered, so VAI minting + /// records the same on-chain price history as the borrow path. Extracted from `mintVAI` to avoid + /// stack-too-deep in that function. + function _updateProtectionStateForEnteredMarkets(address minter) private { + IDeviationBoundedOracle dbo = comptroller.deviationBoundedOracle(); + VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter); + uint256 enteredLength = enteredMarkets.length; + for (uint256 i; i < enteredLength; ++i) { + dbo.updateProtectionState(address(enteredMarkets[i])); + } + } } diff --git a/contracts/test/imports.sol b/contracts/test/imports.sol new file mode 100644 index 000000000..7b82fc5c5 --- /dev/null +++ b/contracts/test/imports.sol @@ -0,0 +1,6 @@ +// SPDX-License-Identifier: BSD-3-Clause +pragma solidity 0.8.25; + +// Force Hardhat to compile DeviationBoundedOracle from node_modules so that +// @openzeppelin/hardhat-upgrades can run storage-layout validation. +import { DeviationBoundedOracle } from "@venusprotocol/oracle/contracts/DeviationBoundedOracle.sol"; diff --git a/deployments/bscmainnet.json b/deployments/bscmainnet.json index 12dbcb054..d428744c6 100644 --- a/deployments/bscmainnet.json +++ b/deployments/bscmainnet.json @@ -8902,7 +8902,7 @@ ] }, "ComptrollerLens": { - "address": "0x732138e18fa6f8f8E456ad829DB429A450a79758", + "address": "0x75A71Ad878f6f24616A2AE21d046C0C8E72f67F8", "abi": [ { "inputs": [], @@ -11976,7 +11976,7 @@ ] }, "FlashLoanFacet": { - "address": "0x72a284f144F2BE56549573DDFac2A90F8D662ed1", + "address": "0x7F00af2f30a55e79311392C98fBBfA629D19b3A5", "abi": [ { "inputs": [], @@ -12537,6 +12537,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -35551,7 +35564,7 @@ ] }, "MarketFacet": { - "address": "0x87FdF72FA2fB29Cb43f03aCa261A8DC2C613a860", + "address": "0x7397B6bcFA9332Cc8791c886F339B4D114651719", "abi": [ { "inputs": [], @@ -36264,6 +36277,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -40527,7 +40553,7 @@ ] }, "PolicyFacet": { - "address": "0x3C115aA5800A589D1E0c3163f3f562D5544F060f", + "address": "0x1CcDaf39085bae4e27c3Ba100561b1AD1B5A6b80", "abi": [ { "inputs": [], @@ -41183,6 +41209,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -48108,7 +48147,7 @@ ] }, "RewardFacet": { - "address": "0x7fcEc39e83f17469069b7A0f24A59B5BbEC0faBb", + "address": "0xFaC00Dc856F454BB674c8588d4CC16Edef9dc28b", "abi": [ { "inputs": [], @@ -48812,6 +48851,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -50270,7 +50322,7 @@ ] }, "SetterFacet": { - "address": "0x11B38582c61058eDd9a526561567B4c7b02060e7", + "address": "0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0", "abi": [ { "inputs": [], @@ -50802,6 +50854,25 @@ "name": "NewComptrollerLens", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "oldDeviationBoundedOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "NewDeviationBoundedOracle", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -51793,6 +51864,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -52226,6 +52310,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "setDeviationBoundedOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -65991,7 +66094,7 @@ ] }, "Unitroller_Implementation": { - "address": "0xB2243Da976F2cbAAa4dd1a76BF7F6EFbe22c4CFc", + "address": "0x82cA18785BBbacBeD1C4f482921E2B2E989D8C08", "abi": [ { "anonymous": false, @@ -66210,6 +66313,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -78135,7 +78251,7 @@ ] }, "VaiUnitroller_Implementation": { - "address": "0xFD754b21F5dbbf6eb282911Cc0112cbF88190767", + "address": "0x8A7d8589A597619A7842d3BC284b9a5a276FaE56", "abi": [ { "anonymous": false, diff --git a/deployments/bscmainnet/ComptrollerLens.json b/deployments/bscmainnet/ComptrollerLens.json index 37f05689d..072da99e2 100644 --- a/deployments/bscmainnet/ComptrollerLens.json +++ b/deployments/bscmainnet/ComptrollerLens.json @@ -1,5 +1,5 @@ { - "address": "0x732138e18fa6f8f8E456ad829DB429A450a79758", + "address": "0x75A71Ad878f6f24616A2AE21d046C0C8E72f67F8", "abi": [ { "inputs": [], @@ -413,28 +413,28 @@ "type": "function" } ], - "transactionHash": "0x393e62d8ababfa0b58493385c4fd35605e495bc68ddb6be536402800393d8df8", + "transactionHash": "0xa0882822deb5e3ff6f3ee178c14cd0557fe3e905f76e0170f0023515b7d41912", "receipt": { "to": null, - "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x732138e18fa6f8f8E456ad829DB429A450a79758", - "transactionIndex": 216, - "gasUsed": "1179290", + "from": "0x9b0A3EAE7f174937d31745B710BbeA68e9D1BEf7", + "contractAddress": "0x75A71Ad878f6f24616A2AE21d046C0C8E72f67F8", + "transactionIndex": 79, + "gasUsed": "1283784", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x53440c5142ea997dbc9d83bf7b0a32520a58d4ecb430f2e26d21f384985a58e7", - "transactionHash": "0x393e62d8ababfa0b58493385c4fd35605e495bc68ddb6be536402800393d8df8", + "blockHash": "0x0c8c7d4d587338b4f1d467eb1b67730df33be189e313dda662843ad92cb10690", + "transactionHash": "0xa0882822deb5e3ff6f3ee178c14cd0557fe3e905f76e0170f0023515b7d41912", "logs": [], - "blockNumber": 66298649, - "cumulativeGasUsed": "33948179", + "blockNumber": 95560322, + "cumulativeGasUsed": "17824001", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 4, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"},{\"internalType\":\"enum WeightFunction\",\"name\":\"weightingStrategy\",\"type\":\"uint8\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateVAICalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"getHypotheticalAccountLiquidity(address,address,address,uint256,uint256,uint8)\":{\"params\":{\"account\":\"Address of the borrowed vToken\",\"borrowAmount\":\"Amount borrowed\",\"comptroller\":\"Address of comptroller\",\"redeemTokens\":\"Number of vTokens being redeemed\",\"vTokenModify\":\"Address of collateral for vToken\",\"weightingStrategy\":\"The weighting strategy to use: - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\"},\"returns\":{\"_0\":\"Returns a tuple of error code, liquidity, and shortfall\"}},\"liquidateCalculateSeizeTokens(address,address,address,address,uint256)\":{\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of total borrowed amount\",\"borrower\":\"Address of borrower whose collateral is being seized\",\"comptroller\":\"Address of comptroller\",\"vTokenBorrowed\":\"Address of the borrowed vToken\",\"vTokenCollateral\":\"Address of collateral for the borrow\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"details\":\"This will be used only in vBNB\",\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of total borrowed amount\",\"comptroller\":\"Address of comptroller\",\"vTokenBorrowed\":\"Address of the borrowed vToken\",\"vTokenCollateral\":\"Address of collateral for the borrow\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}},\"liquidateVAICalculateSeizeTokens(address,address,uint256)\":{\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of the total borrowed amount\",\"comptroller\":\"Address of comptroller\",\"vTokenCollateral\":\"Address of collateral for vToken\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}}},\"title\":\"ComptrollerLens Contract\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"kind\":\"user\",\"methods\":{\"getHypotheticalAccountLiquidity(address,address,address,uint256,uint256,uint8)\":{\"notice\":\"Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow A snapshot of the account is taken and the total borrow amount of the account is calculated\"},\"liquidateCalculateSeizeTokens(address,address,address,address,uint256)\":{\"notice\":\"Computes the number of collateral tokens to be seized in a liquidation event\"},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"notice\":\"Computes the number of collateral tokens to be seized in a liquidation event\"},\"liquidateVAICalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Computes the number of VAI tokens to be seized in a liquidation event\"}},\"notice\":\"The ComptrollerLens contract has functions to get the number of tokens that can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/ComptrollerLens.sol\":\"ComptrollerLens\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/ComptrollerLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { ExponentialNoError } from \\\"../Utils/ExponentialNoError.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../Utils/ErrorReporter.sol\\\";\\nimport { ComptrollerInterface } from \\\"../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../Comptroller/ComptrollerLensInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title ComptrollerLens Contract\\n * @author Venus\\n * @notice The ComptrollerLens contract has functions to get the number of tokens that\\n * can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\\n */\\ncontract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, ExponentialNoError {\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint vTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp weightedFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\\n * @dev This will be used only in vBNB\\n * @param comptroller Address of comptroller\\n * @param vTokenBorrowed Address of the borrowed vToken\\n * @param vTokenCollateral Address of collateral for the borrow\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\\n\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\\n * @param borrower Address of borrower whose collateral is being seized\\n * @param comptroller Address of comptroller\\n * @param vTokenBorrowed Address of the borrowed vToken\\n * @param vTokenCollateral Address of collateral for the borrow\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getEffectiveLiquidationIncentive(\\n borrower,\\n vTokenCollateral\\n );\\n\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the number of VAI tokens to be seized in a liquidation event\\n * @param comptroller Address of comptroller\\n * @param vTokenCollateral Address of collateral for vToken\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of the total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = 1e18; // Note: this is VAI\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow\\n * A snapshot of the account is taken and the total borrow amount of the account is calculated\\n * @param comptroller Address of comptroller\\n * @param account Address of the borrowed vToken\\n * @param vTokenModify Address of collateral for vToken\\n * @param redeemTokens Number of vTokens being redeemed\\n * @param borrowAmount Amount borrowed\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return Returns a tuple of error code, liquidity, and shortfall\\n */\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint) {\\n (uint errorCode, AccountLiquidityLocalVars memory vars) = _calculateAccountPosition(\\n comptroller,\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n if (errorCode != 0) {\\n return (errorCode, 0, 0);\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (uint(Error.NO_ERROR), vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (uint(Error.NO_ERROR), 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Internal function to calculate account position\\n * @param comptroller Address of comptroller\\n * @param account Address of the account whose liquidity is being calculated\\n * @param vTokenModify The vToken being modified (redeemed or borrowed)\\n * @param redeemTokens Number of vTokens being redeemed\\n * @param borrowAmount Amount borrowed\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return oErr Returns an error code indicating success or failure\\n * @return vars Returns an AccountLiquidityLocalVars struct containing the calculated values\\n */\\n function _calculateAccountPosition(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint oErr, AccountLiquidityLocalVars memory vars) {\\n // For each asset the account is in\\n VToken[] memory assets = ComptrollerInterface(comptroller).getAssetsIn(account);\\n uint assetsCount = assets.length;\\n for (uint i = 0; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(\\n account\\n );\\n if (oErr != 0) {\\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (uint(Error.SNAPSHOT_ERROR), vars);\\n }\\n vars.weightedFactor = Exp({\\n mantissa: ComptrollerInterface(comptroller).getEffectiveLtvFactor(\\n account,\\n address(asset),\\n weightingStrategy\\n )\\n });\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(address(asset));\\n if (vars.oraclePriceMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), vars);\\n }\\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n\\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\\n vars.tokensToDenom = mul_(mul_(vars.weightedFactor, vars.exchangeRate), vars.oraclePrice);\\n\\n // sumCollateral += tokensToDenom * vTokenBalance\\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.vTokenBalance, vars.sumCollateral);\\n\\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.oraclePrice,\\n vars.borrowBalance,\\n vars.sumBorrowPlusEffects\\n );\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.tokensToDenom,\\n redeemTokens,\\n vars.sumBorrowPlusEffects\\n );\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.oraclePrice,\\n borrowAmount,\\n vars.sumBorrowPlusEffects\\n );\\n }\\n }\\n\\n VAIControllerInterface vaiController = ComptrollerInterface(comptroller).vaiController();\\n\\n if (address(vaiController) != address(0)) {\\n vars.sumBorrowPlusEffects = add_(vars.sumBorrowPlusEffects, vaiController.getVAIRepayAmount(account));\\n }\\n oErr = uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Calculate the number of tokens to seize during liquidation\\n * @param actualRepayAmount The amount of debt being repaid in the liquidation\\n * @param liquidationIncentiveMantissa The liquidation incentive, scaled by 1e18\\n * @param priceBorrowedMantissa The price of the borrowed asset, scaled by 1e18\\n * @param priceCollateralMantissa The price of the collateral asset, scaled by 1e18\\n * @param exchangeRateMantissa The exchange rate of the collateral asset, scaled by 1e18\\n * @return seizeTokens The number of tokens to seize during liquidation, scaled by 1e18\\n */\\n function _calculateSeizeTokens(\\n uint actualRepayAmount,\\n uint liquidationIncentiveMantissa,\\n uint priceBorrowedMantissa,\\n uint priceCollateralMantissa,\\n uint exchangeRateMantissa\\n ) internal pure returns (uint seizeTokens) {\\n Exp memory numerator = mul_(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n Exp({ mantissa: priceBorrowedMantissa })\\n );\\n Exp memory denominator = mul_(\\n Exp({ mantissa: priceCollateralMantissa }),\\n Exp({ mantissa: exchangeRateMantissa })\\n );\\n\\n seizeTokens = mul_ScalarTruncate(div_(numerator, denominator), actualRepayAmount);\\n }\\n}\\n\",\"keccak256\":\"0xefc0992c2559e8dfac700aa3c34f41f117d30f3e5de0f91be83e0113f83b1020\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506114588061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630ef332ca1461004e57806313d97e2c1461007b578063a5d5a0501461008e578063f7a9183e146100a1575b5f80fd5b61006161005c36600461108f565b6100cf565b604080519283526020830191909152015b60405180910390f35b6100616100893660046110dd565b61037b565b61006161009c36600461111b565b61055c565b6100b46100af36600461117b565b610811565b60408051938452602084019290925290820152606001610072565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013291906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c9190611205565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ff91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610245573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102699190611205565b9050811580610276575080155b1561028957600d5f935093505050610372565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102ea9190611205565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918b169063d686e9ee90602401602060405180830381865afa158015610333573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103579190611205565b90505f6103678883878787610892565b5f9750955050505050505b94509492505050565b5f805f670de0b6b3a764000090505f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610430573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104549190611205565b9050805f0361046b57600d5f935093505050610554565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104cc9190611205565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918a169063d686e9ee90602401602060405180830381865afa158015610515573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105399190611205565b90505f6105498883878787610892565b5f9750955050505050505b935093915050565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105bf91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610605573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106299190611205565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa1580156106d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f69190611205565b9050811580610703575080155b1561071657600d5f935093505050610807565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610753573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107779190611205565b60405163afd3783b60e01b81526001600160a01b038c8116600483015289811660248301529192505f918b169063afd3783b90604401602060405180830381865afa1580156107c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ec9190611205565b90505f6107fc8883878787610892565b5f9750955050505050505b9550959350505050565b5f805f805f6108248b8b8b8b8b8b610904565b91509150815f1461083d575092505f9150819050610886565b60208101518151111561086a575f6020820151825161085c9190611230565b5f9450945094505050610886565b5f815160208301515f9161087d91611230565b94509450945050505b96509650969350505050565b5f806108ba604051806020016040528088815250604051806020016040528088815250610d75565b90505f6108e3604051806020016040528087815250604051806020016040528087815250610d75565b90506108f86108f28383610dbc565b89610df4565b98975050505050505050565b5f61090d610fe0565b604051632aff3bff60e21b81526001600160a01b0388811660048301525f91908a169063abfceffc906024015f60405180830381865afa158015610953573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261097a9190810190611267565b80519091505f5b81811015610c72575f83828151811061099c5761099c61131b565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038d811660048301529192509082169063c37f68e290602401608060405180830381865afa1580156109ef573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a13919061132f565b60808901526060880152604087015295508515610a3857600f5b955050505050610d6a565b6040805160208101918290526319ef3e8b60e01b909152806001600160a01b038e166319ef3e8b610a6e8f868d60248701611362565b602060405180830381865afa158015610a89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aad9190611205565b905260c086015260408051602080820183526080880151825260e088019190915281516307dc0d1d60e41b815291516001600160a01b038f1692637dc0d1d09260048083019391928290030181865afa158015610b0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3091906111ea565b60405163fc57d4df60e01b81526001600160a01b038381166004830152919091169063fc57d4df90602401602060405180830381865afa158015610b76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9a9190611205565b60a086018190525f03610bae57600d610a2d565b604080516020810190915260a0860151815261010086015260c085015160e0860151610be891610bdd91610d75565b866101000151610d75565b610120860181905260408601518651610c02929190610e13565b855261010085015160608601516020870151610c1f929190610e13565b60208601526001600160a01b03808b1690821603610c6957610c4b8561012001518a8760200151610e13565b60208601819052610100860151610c63918a90610e13565b60208601525b50600101610981565b505f8a6001600160a01b0316639254f5e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cb0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cd491906111ea565b90506001600160a01b03811615610d63576020840151604051633c617c9160e11b81526001600160a01b038c81166004830152610d5d9291908416906378c2f92290602401602060405180830381865afa158015610d34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d589190611205565b610e3e565b60208501525b5f94505050505b965096945050505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610da7865f0151865f0151610e73565b610db191906113a4565b905290505b92915050565b60408051602081019091525f81526040518060200160405280610db1610ded865f0151670de0b6b3a7640000610e73565b8551610eb4565b5f80610e008484610ee6565b9050610e0b81610f0c565b949350505050565b5f80610e1f8585610ee6565b9050610e33610e2d82610f0c565b84610e3e565b9150505b9392505050565b5f610e378383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250610f23565b5f610e3783836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250610f65565b5f610e3783836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250610fb5565b60408051602081019091525f81526040518060200160405280610db1855f015185610e73565b80515f90610db690670de0b6b3a7640000906113a4565b5f80610f2f84866113c3565b90508285821015610f5c5760405162461bcd60e51b8152600401610f5391906113d6565b60405180910390fd5b50949350505050565b5f831580610f71575082155b15610f7d57505f610e37565b5f610f88848661140b565b905083610f9586836113a4565b148390610f5c5760405162461bcd60e51b8152600401610f5391906113d6565b5f8183610fd55760405162461bcd60e51b8152600401610f5391906113d6565b50610e0b83856113a4565b6040518061014001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f815260200161102560405180602001604052805f81525090565b815260200161103f60405180602001604052805f81525090565b815260200161105960405180602001604052805f81525090565b815260200161107360405180602001604052805f81525090565b905290565b6001600160a01b038116811461108c575f80fd5b50565b5f805f80608085870312156110a2575f80fd5b84356110ad81611078565b935060208501356110bd81611078565b925060408501356110cd81611078565b9396929550929360600135925050565b5f805f606084860312156110ef575f80fd5b83356110fa81611078565b9250602084013561110a81611078565b929592945050506040919091013590565b5f805f805f60a0868803121561112f575f80fd5b853561113a81611078565b9450602086013561114a81611078565b9350604086013561115a81611078565b9250606086013561116a81611078565b949793965091946080013592915050565b5f805f805f8060c08789031215611190575f80fd5b863561119b81611078565b955060208701356111ab81611078565b945060408701356111bb81611078565b9350606087013592506080870135915060a0870135600281106111dc575f80fd5b809150509295509295509295565b5f602082840312156111fa575f80fd5b8151610e3781611078565b5f60208284031215611215575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610db657610db661121c565b634e487b7160e01b5f52604160045260245ffd5b805161126281611078565b919050565b5f6020808385031215611278575f80fd5b825167ffffffffffffffff8082111561128f575f80fd5b818501915085601f8301126112a2575f80fd5b8151818111156112b4576112b4611243565b8060051b604051601f19603f830116810181811085821117156112d9576112d9611243565b6040529182528482019250838101850191888311156112f6575f80fd5b938501935b828510156108f85761130c85611257565b845293850193928501926112fb565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215611342575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061139657634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f826113be57634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610db657610db661121c565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082028115828204841417610db657610db661121c56fea2646970667358221220e8be33df18536bccf2d1e6d46cfdf853d20157902cc0f52c55cbf116e851f31264736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630ef332ca1461004e57806313d97e2c1461007b578063a5d5a0501461008e578063f7a9183e146100a1575b5f80fd5b61006161005c36600461108f565b6100cf565b604080519283526020830191909152015b60405180910390f35b6100616100893660046110dd565b61037b565b61006161009c36600461111b565b61055c565b6100b46100af36600461117b565b610811565b60408051938452602084019290925290820152606001610072565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013291906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c9190611205565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ff91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610245573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102699190611205565b9050811580610276575080155b1561028957600d5f935093505050610372565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102ea9190611205565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918b169063d686e9ee90602401602060405180830381865afa158015610333573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103579190611205565b90505f6103678883878787610892565b5f9750955050505050505b94509492505050565b5f805f670de0b6b3a764000090505f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610430573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104549190611205565b9050805f0361046b57600d5f935093505050610554565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104cc9190611205565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918a169063d686e9ee90602401602060405180830381865afa158015610515573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105399190611205565b90505f6105498883878787610892565b5f9750955050505050505b935093915050565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105bf91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610605573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106299190611205565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa1580156106d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f69190611205565b9050811580610703575080155b1561071657600d5f935093505050610807565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610753573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107779190611205565b60405163afd3783b60e01b81526001600160a01b038c8116600483015289811660248301529192505f918b169063afd3783b90604401602060405180830381865afa1580156107c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ec9190611205565b90505f6107fc8883878787610892565b5f9750955050505050505b9550959350505050565b5f805f805f6108248b8b8b8b8b8b610904565b91509150815f1461083d575092505f9150819050610886565b60208101518151111561086a575f6020820151825161085c9190611230565b5f9450945094505050610886565b5f815160208301515f9161087d91611230565b94509450945050505b96509650969350505050565b5f806108ba604051806020016040528088815250604051806020016040528088815250610d75565b90505f6108e3604051806020016040528087815250604051806020016040528087815250610d75565b90506108f86108f28383610dbc565b89610df4565b98975050505050505050565b5f61090d610fe0565b604051632aff3bff60e21b81526001600160a01b0388811660048301525f91908a169063abfceffc906024015f60405180830381865afa158015610953573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261097a9190810190611267565b80519091505f5b81811015610c72575f83828151811061099c5761099c61131b565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038d811660048301529192509082169063c37f68e290602401608060405180830381865afa1580156109ef573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a13919061132f565b60808901526060880152604087015295508515610a3857600f5b955050505050610d6a565b6040805160208101918290526319ef3e8b60e01b909152806001600160a01b038e166319ef3e8b610a6e8f868d60248701611362565b602060405180830381865afa158015610a89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aad9190611205565b905260c086015260408051602080820183526080880151825260e088019190915281516307dc0d1d60e41b815291516001600160a01b038f1692637dc0d1d09260048083019391928290030181865afa158015610b0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3091906111ea565b60405163fc57d4df60e01b81526001600160a01b038381166004830152919091169063fc57d4df90602401602060405180830381865afa158015610b76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9a9190611205565b60a086018190525f03610bae57600d610a2d565b604080516020810190915260a0860151815261010086015260c085015160e0860151610be891610bdd91610d75565b866101000151610d75565b610120860181905260408601518651610c02929190610e13565b855261010085015160608601516020870151610c1f929190610e13565b60208601526001600160a01b03808b1690821603610c6957610c4b8561012001518a8760200151610e13565b60208601819052610100860151610c63918a90610e13565b60208601525b50600101610981565b505f8a6001600160a01b0316639254f5e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cb0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cd491906111ea565b90506001600160a01b03811615610d63576020840151604051633c617c9160e11b81526001600160a01b038c81166004830152610d5d9291908416906378c2f92290602401602060405180830381865afa158015610d34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d589190611205565b610e3e565b60208501525b5f94505050505b965096945050505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610da7865f0151865f0151610e73565b610db191906113a4565b905290505b92915050565b60408051602081019091525f81526040518060200160405280610db1610ded865f0151670de0b6b3a7640000610e73565b8551610eb4565b5f80610e008484610ee6565b9050610e0b81610f0c565b949350505050565b5f80610e1f8585610ee6565b9050610e33610e2d82610f0c565b84610e3e565b9150505b9392505050565b5f610e378383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250610f23565b5f610e3783836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250610f65565b5f610e3783836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250610fb5565b60408051602081019091525f81526040518060200160405280610db1855f015185610e73565b80515f90610db690670de0b6b3a7640000906113a4565b5f80610f2f84866113c3565b90508285821015610f5c5760405162461bcd60e51b8152600401610f5391906113d6565b60405180910390fd5b50949350505050565b5f831580610f71575082155b15610f7d57505f610e37565b5f610f88848661140b565b905083610f9586836113a4565b148390610f5c5760405162461bcd60e51b8152600401610f5391906113d6565b5f8183610fd55760405162461bcd60e51b8152600401610f5391906113d6565b50610e0b83856113a4565b6040518061014001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f815260200161102560405180602001604052805f81525090565b815260200161103f60405180602001604052805f81525090565b815260200161105960405180602001604052805f81525090565b815260200161107360405180602001604052805f81525090565b905290565b6001600160a01b038116811461108c575f80fd5b50565b5f805f80608085870312156110a2575f80fd5b84356110ad81611078565b935060208501356110bd81611078565b925060408501356110cd81611078565b9396929550929360600135925050565b5f805f606084860312156110ef575f80fd5b83356110fa81611078565b9250602084013561110a81611078565b929592945050506040919091013590565b5f805f805f60a0868803121561112f575f80fd5b853561113a81611078565b9450602086013561114a81611078565b9350604086013561115a81611078565b9250606086013561116a81611078565b949793965091946080013592915050565b5f805f805f8060c08789031215611190575f80fd5b863561119b81611078565b955060208701356111ab81611078565b945060408701356111bb81611078565b9350606087013592506080870135915060a0870135600281106111dc575f80fd5b809150509295509295509295565b5f602082840312156111fa575f80fd5b8151610e3781611078565b5f60208284031215611215575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610db657610db661121c565b634e487b7160e01b5f52604160045260245ffd5b805161126281611078565b919050565b5f6020808385031215611278575f80fd5b825167ffffffffffffffff8082111561128f575f80fd5b818501915085601f8301126112a2575f80fd5b8151818111156112b4576112b4611243565b8060051b604051601f19603f830116810181811085821117156112d9576112d9611243565b6040529182528482019250838101850191888311156112f6575f80fd5b938501935b828510156108f85761130c85611257565b845293850193928501926112fb565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215611342575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061139657634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f826113be57634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610db657610db661121c565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082028115828204841417610db657610db661121c56fea2646970667358221220e8be33df18536bccf2d1e6d46cfdf853d20157902cc0f52c55cbf116e851f31264736f6c63430008190033", + "numDeployments": 5, + "solcInputHash": "cbc4287e135101fe4c78448d0f5f2ecc", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"},{\"internalType\":\"enum WeightFunction\",\"name\":\"weightingStrategy\",\"type\":\"uint8\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateVAICalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"getHypotheticalAccountLiquidity(address,address,address,uint256,uint256,uint8)\":{\"params\":{\"account\":\"Address of the borrowed vToken\",\"borrowAmount\":\"Amount borrowed\",\"comptroller\":\"Address of comptroller\",\"redeemTokens\":\"Number of vTokens being redeemed\",\"vTokenModify\":\"Address of collateral for vToken\",\"weightingStrategy\":\"The weighting strategy to use: - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\"},\"returns\":{\"_0\":\"Returns a tuple of error code, liquidity, and shortfall\"}},\"liquidateCalculateSeizeTokens(address,address,address,address,uint256)\":{\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of total borrowed amount\",\"borrower\":\"Address of borrower whose collateral is being seized\",\"comptroller\":\"Address of comptroller\",\"vTokenBorrowed\":\"Address of the borrowed vToken\",\"vTokenCollateral\":\"Address of collateral for the borrow\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"details\":\"This will be used only in vBNB\",\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of total borrowed amount\",\"comptroller\":\"Address of comptroller\",\"vTokenBorrowed\":\"Address of the borrowed vToken\",\"vTokenCollateral\":\"Address of collateral for the borrow\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}},\"liquidateVAICalculateSeizeTokens(address,address,uint256)\":{\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of the total borrowed amount\",\"comptroller\":\"Address of comptroller\",\"vTokenCollateral\":\"Address of collateral for vToken\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}}},\"title\":\"ComptrollerLens Contract\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"kind\":\"user\",\"methods\":{\"getHypotheticalAccountLiquidity(address,address,address,uint256,uint256,uint8)\":{\"notice\":\"Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow A snapshot of the account is taken and the total borrow amount of the account is calculated\"},\"liquidateCalculateSeizeTokens(address,address,address,address,uint256)\":{\"notice\":\"Computes the number of collateral tokens to be seized in a liquidation event\"},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"notice\":\"Computes the number of collateral tokens to be seized in a liquidation event\"},\"liquidateVAICalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Computes the number of VAI tokens to be seized in a liquidation event\"}},\"notice\":\"The ComptrollerLens contract has functions to get the number of tokens that can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/ComptrollerLens.sol\":\"ComptrollerLens\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\\n enum KeeperAction {\\n SetMinPrice,\\n SetMaxPrice,\\n ExitProtectionMode\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool cachingEnabled;\\n }\\n\\n /// @notice One item in an syncPriceBoundsAndProtections payload\\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\\n struct KeeperActionItem {\\n address asset;\\n KeeperAction action;\\n uint256 value;\\n }\\n\\n /// @notice One item in a setTokenConfigs payload\\n struct TokenConfigInput {\\n /// @notice The underlying asset address\\n address asset;\\n /// @notice Minimum time protection stays active after the last trigger (seconds)\\n uint64 cooldownPeriod;\\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\\n uint256 triggerThreshold;\\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\\n uint256 resetThreshold;\\n /// @notice Whether to enable bounded pricing immediately upon initialization\\n bool enableBoundedPricing;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool enableCaching;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n /// @notice Emitted when the per-asset transient caching flag is toggled\\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\\n error InvalidKeeperAction(uint8 action);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage. The transient\\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n /**\\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\\n * Empty `actions` is a no-op success.\\n * @param actions The list of keeper actions to apply\\n * @custom:access Only authorized keeper addresses\\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\\n */\\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param tokenConfig_ Token config input for the asset\\n * @custom:access Only Governance\\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param tokenConfigs_ Array of token config inputs, one per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if the input array is empty\\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\\n * @custom:error VAINotAllowed if any asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n /**\\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\\n * live spot instead of reading or writing the transient slots. The initial value is\\n * set via the `enableCaching` argument of `setTokenConfig`.\\n * @param asset The underlying asset address\\n * @param enabled Whether transient caching is enabled for this asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CachingEnabledUpdated\\n */\\n function setCachingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold,\\n bool cachingEnabled\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0xe223d88c17c0d752fdb33fa223b63ce124a798512f3d69f3800e9508e7dff931\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/ComptrollerLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { ExponentialNoError } from \\\"../Utils/ExponentialNoError.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../Utils/ErrorReporter.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { ComptrollerInterface } from \\\"../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../Comptroller/ComptrollerLensInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title ComptrollerLens Contract\\n * @author Venus\\n * @notice The ComptrollerLens contract has functions to get the number of tokens that\\n * can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\\n */\\ncontract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, ExponentialNoError {\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint vTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp weightedFactor;\\n Exp exchangeRate;\\n Exp tokensToDenom;\\n Exp collateralPrice;\\n Exp debtPrice;\\n IDeviationBoundedOracle boundedOracle;\\n ResilientOracleInterface spotOracle;\\n }\\n\\n /**\\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\\n * @dev This will be used only in vBNB\\n * @param comptroller Address of comptroller\\n * @param vTokenBorrowed Address of the borrowed vToken\\n * @param vTokenCollateral Address of collateral for the borrow\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\\n\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\\n * @param borrower Address of borrower whose collateral is being seized\\n * @param comptroller Address of comptroller\\n * @param vTokenBorrowed Address of the borrowed vToken\\n * @param vTokenCollateral Address of collateral for the borrow\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getEffectiveLiquidationIncentive(\\n borrower,\\n vTokenCollateral\\n );\\n\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the number of VAI tokens to be seized in a liquidation event\\n * @param comptroller Address of comptroller\\n * @param vTokenCollateral Address of collateral for vToken\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of the total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = 1e18; // Note: this is VAI\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow\\n * A snapshot of the account is taken and the total borrow amount of the account is calculated\\n * @param comptroller Address of comptroller\\n * @param account Address of the borrowed vToken\\n * @param vTokenModify Address of collateral for vToken\\n * @param redeemTokens Number of vTokens being redeemed\\n * @param borrowAmount Amount borrowed\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return Returns a tuple of error code, liquidity, and shortfall\\n */\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint) {\\n (uint errorCode, AccountLiquidityLocalVars memory vars) = _calculateAccountPosition(\\n comptroller,\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n if (errorCode != 0) {\\n return (errorCode, 0, 0);\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (uint(Error.NO_ERROR), vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (uint(Error.NO_ERROR), 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Computes an account's aggregate weighted-collateral and total-borrow values,\\n * optionally applying hypothetical redeem/borrow effects on a single market.\\n * @dev Pricing differs by weighting strategy:\\n * - USE_COLLATERAL_FACTOR: collateral is valued at `DeviationBoundedOracle.getBoundedCollateralPriceView`,\\n * borrows at `getBoundedDebtPriceView`.\\n * - USE_LIQUIDATION_THRESHOLD: both collateral and borrows use the spot oracle price.\\n * VAI borrows (from `vaiController.getVAIRepayAmount`) are added to `sumBorrowPlusEffects` after\\n * the per-asset loop, regardless of weighting strategy.\\n * @param comptroller Address of the comptroller whose markets and oracle are used\\n * @param account Address of the account whose position is being computed\\n * @param vTokenModify Market to apply hypothetical effects on; pass `VToken(address(0))` for none\\n * @param redeemTokens Number of vTokens hypothetically redeemed from `vTokenModify`\\n * @param borrowAmount Amount of underlying hypothetically borrowed from `vTokenModify`\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return oErr 0 on success, or a non-zero `Error` code (SNAPSHOT_ERROR or PRICE_ERROR) on failure\\n * @return vars Accumulated position data; `sumCollateral` and `sumBorrowPlusEffects` are the primary outputs\\n */\\n function _calculateAccountPosition(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint oErr, AccountLiquidityLocalVars memory vars) {\\n // For each asset the account is in\\n VToken[] memory assets = ComptrollerInterface(comptroller).getAssetsIn(account);\\n uint assetsCount = assets.length;\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n vars.boundedOracle = ComptrollerInterface(comptroller).deviationBoundedOracle();\\n } else {\\n vars.spotOracle = ComptrollerInterface(comptroller).oracle();\\n }\\n for (uint i = 0; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(\\n account\\n );\\n if (oErr != 0) {\\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (uint(Error.SNAPSHOT_ERROR), vars);\\n }\\n vars.weightedFactor = Exp({\\n mantissa: ComptrollerInterface(comptroller).getEffectiveLtvFactor(\\n account,\\n address(asset),\\n weightingStrategy\\n )\\n });\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n // Determine bounded prices for CF path\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n (uint256 collateralPriceMantissa, uint256 debtPriceMantissa) = vars.boundedOracle.getBoundedPricesView(\\n address(asset)\\n );\\n if (collateralPriceMantissa == 0 || debtPriceMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), vars);\\n }\\n vars.collateralPrice = Exp({ mantissa: collateralPriceMantissa });\\n vars.debtPrice = Exp({ mantissa: debtPriceMantissa });\\n } else {\\n // LT path \\u2014 always spot\\n vars.oraclePriceMantissa = vars.spotOracle.getUnderlyingPrice(address(asset));\\n if (vars.oraclePriceMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), vars);\\n }\\n vars.collateralPrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n vars.debtPrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n }\\n\\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\\n vars.tokensToDenom = mul_(mul_(vars.weightedFactor, vars.exchangeRate), vars.collateralPrice);\\n\\n // sumCollateral += tokensToDenom * vTokenBalance\\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.vTokenBalance, vars.sumCollateral);\\n\\n // sumBorrowPlusEffects += debtPrice * borrowBalance\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.debtPrice,\\n vars.borrowBalance,\\n vars.sumBorrowPlusEffects\\n );\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect \\u2014 uses collateral-bounded tokensToDenom\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.tokensToDenom,\\n redeemTokens,\\n vars.sumBorrowPlusEffects\\n );\\n\\n // borrow effect \\u2014 uses debt-bounded price\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.debtPrice,\\n borrowAmount,\\n vars.sumBorrowPlusEffects\\n );\\n }\\n }\\n\\n VAIControllerInterface vaiController = ComptrollerInterface(comptroller).vaiController();\\n\\n if (address(vaiController) != address(0)) {\\n vars.sumBorrowPlusEffects = add_(vars.sumBorrowPlusEffects, vaiController.getVAIRepayAmount(account));\\n }\\n oErr = uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Calculate the number of tokens to seize during liquidation\\n * @param actualRepayAmount The amount of debt being repaid in the liquidation\\n * @param liquidationIncentiveMantissa The liquidation incentive, scaled by 1e18\\n * @param priceBorrowedMantissa The price of the borrowed asset, scaled by 1e18\\n * @param priceCollateralMantissa The price of the collateral asset, scaled by 1e18\\n * @param exchangeRateMantissa The exchange rate of the collateral asset, scaled by 1e18\\n * @return seizeTokens The number of tokens to seize during liquidation, scaled by 1e18\\n */\\n function _calculateSeizeTokens(\\n uint actualRepayAmount,\\n uint liquidationIncentiveMantissa,\\n uint priceBorrowedMantissa,\\n uint priceCollateralMantissa,\\n uint exchangeRateMantissa\\n ) internal pure returns (uint seizeTokens) {\\n Exp memory numerator = mul_(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n Exp({ mantissa: priceBorrowedMantissa })\\n );\\n Exp memory denominator = mul_(\\n Exp({ mantissa: priceCollateralMantissa }),\\n Exp({ mantissa: exchangeRateMantissa })\\n );\\n\\n seizeTokens = mul_ScalarTruncate(div_(numerator, denominator), actualRepayAmount);\\n }\\n}\\n\",\"keccak256\":\"0x910f072609bc6200b550bb5498ec0d2a6603e75dc1da8a7b7e8f5f4846019ee4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b5061163b8061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630ef332ca1461004e57806313d97e2c1461007b578063a5d5a0501461008e578063f7a9183e146100a1575b5f80fd5b61006161005c36600461123c565b6100cf565b604080519283526020830191909152015b60405180910390f35b61006161008936600461128a565b61037b565b61006161009c3660046112c8565b61055c565b6100b46100af366004611328565b610811565b60408051938452602084019290925290820152606001610072565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101329190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c91906113b2565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ff9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610245573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061026991906113b2565b9050811580610276575080155b1561028957600d5f935093505050610372565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102ea91906113b2565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918b169063d686e9ee90602401602060405180830381865afa158015610333573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061035791906113b2565b90505f6103678883878787610892565b5f9750955050505050505b94509492505050565b5f805f670de0b6b3a764000090505f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610430573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061045491906113b2565b9050805f0361046b57600d5f935093505050610554565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104cc91906113b2565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918a169063d686e9ee90602401602060405180830381865afa158015610515573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053991906113b2565b90505f6105498883878787610892565b5f9750955050505050505b935093915050565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105bf9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610605573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062991906113b2565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa1580156106d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f691906113b2565b9050811580610703575080155b1561071657600d5f935093505050610807565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610753573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077791906113b2565b60405163afd3783b60e01b81526001600160a01b038c8116600483015289811660248301529192505f918b169063afd3783b90604401602060405180830381865afa1580156107c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ec91906113b2565b90505f6107fc8883878787610892565b5f9750955050505050505b9550959350505050565b5f805f805f6108248b8b8b8b8b8b610904565b91509150815f1461083d575092505f9150819050610886565b60208101518151111561086a575f6020820151825161085c91906113f1565b5f9450945094505050610886565b5f815160208301515f9161087d916113f1565b94509450945050505b96509650969350505050565b5f806108ba604051806020016040528088815250604051806020016040528088815250610efa565b90505f6108e3604051806020016040528087815250604051806020016040528087815250610efa565b90506108f86108f28383610f41565b89610f79565b98975050505050505050565b5f61090d611165565b604051632aff3bff60e21b81526001600160a01b0388811660048301525f91908a169063abfceffc906024015f60405180830381865afa158015610953573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261097a9190810190611428565b80519091505f856001811115610992576109926113c9565b03610a0b57896001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f79190611397565b6001600160a01b0316610160840152610a7b565b896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a47573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6b9190611397565b6001600160a01b03166101808401525b5f5b81811015610df7575f838281518110610a9857610a986114dc565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038d811660048301529192509082169063c37f68e290602401608060405180830381865afa158015610aeb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b0f91906114f0565b60808901526060880152604087015295508515610b3457600f5b955050505050610eef565b6040805160208101918290526319ef3e8b60e01b909152806001600160a01b038e166319ef3e8b610b6a8f868d60248701611523565b602060405180830381865afa158015610b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906113b2565b905260c086015260408051602081019091526080860151815260e08601525f876001811115610bda57610bda6113c9565b03610c9c576101608501516040516388142b6b60e01b81526001600160a01b0383811660048301525f9283929116906388142b6b906024016040805180830381865afa158015610c2c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c509190611565565b91509150815f1480610c60575080155b15610c7457600d9750505050505050610eef565b6040805160208082018352938152610120890152805192830190528152610140860152610d4d565b61018085015160405163fc57d4df60e01b81526001600160a01b0383811660048301529091169063fc57d4df90602401602060405180830381865afa158015610ce7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d0b91906113b2565b60a086018190525f03610d1f57600d610b29565b604080516020808201835260a088018051835261012089019290925282519081019092525181526101408601525b610d6d610d628660c001518760e00151610efa565b866101200151610efa565b610100860181905260408601518651610d87929190610f98565b855261014085015160608601516020870151610da4929190610f98565b60208601526001600160a01b03808b1690821603610dee57610dd08561010001518a8760200151610f98565b60208601819052610140860151610de8918a90610f98565b60208601525b50600101610a7d565b505f8a6001600160a01b0316639254f5e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e35573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e599190611397565b90506001600160a01b03811615610ee8576020840151604051633c617c9160e11b81526001600160a01b038c81166004830152610ee29291908416906378c2f92290602401602060405180830381865afa158015610eb9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610edd91906113b2565b610fc3565b60208501525b5f94505050505b965096945050505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610f2c865f0151865f0151610ff8565b610f369190611587565b905290505b92915050565b60408051602081019091525f81526040518060200160405280610f36610f72865f0151670de0b6b3a7640000610ff8565b8551611039565b5f80610f85848461106b565b9050610f9081611091565b949350505050565b5f80610fa4858561106b565b9050610fb8610fb282611091565b84610fc3565b9150505b9392505050565b5f610fbc8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b8152506110a8565b5f610fbc83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506110ea565b5f610fbc83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525061113a565b60408051602081019091525f81526040518060200160405280610f36855f015185610ff8565b80515f90610f3b90670de0b6b3a764000090611587565b5f806110b484866115a6565b905082858210156110e15760405162461bcd60e51b81526004016110d891906115b9565b60405180910390fd5b50949350505050565b5f8315806110f6575082155b1561110257505f610fbc565b5f61110d84866115ee565b90508361111a8683611587565b1483906110e15760405162461bcd60e51b81526004016110d891906115b9565b5f818361115a5760405162461bcd60e51b81526004016110d891906115b9565b50610f908385611587565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020016111aa60405180602001604052805f81525090565b81526020016111c460405180602001604052805f81525090565b81526020016111de60405180602001604052805f81525090565b81526020016111f860405180602001604052805f81525090565b815260200161121260405180602001604052805f81525090565b81525f6020820181905260409091015290565b6001600160a01b0381168114611239575f80fd5b50565b5f805f806080858703121561124f575f80fd5b843561125a81611225565b9350602085013561126a81611225565b9250604085013561127a81611225565b9396929550929360600135925050565b5f805f6060848603121561129c575f80fd5b83356112a781611225565b925060208401356112b781611225565b929592945050506040919091013590565b5f805f805f60a086880312156112dc575f80fd5b85356112e781611225565b945060208601356112f781611225565b9350604086013561130781611225565b9250606086013561131781611225565b949793965091946080013592915050565b5f805f805f8060c0878903121561133d575f80fd5b863561134881611225565b9550602087013561135881611225565b9450604087013561136881611225565b9350606087013592506080870135915060a087013560028110611389575f80fd5b809150509295509295509295565b5f602082840312156113a7575f80fd5b8151610fbc81611225565b5f602082840312156113c2575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b81810381811115610f3b57610f3b6113dd565b634e487b7160e01b5f52604160045260245ffd5b805161142381611225565b919050565b5f6020808385031215611439575f80fd5b825167ffffffffffffffff80821115611450575f80fd5b818501915085601f830112611463575f80fd5b81518181111561147557611475611404565b8060051b604051601f19603f8301168101818110858211171561149a5761149a611404565b6040529182528482019250838101850191888311156114b7575f80fd5b938501935b828510156108f8576114cd85611418565b845293850193928501926114bc565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215611503575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061155757634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f8060408385031215611576575f80fd5b505080516020909101519092909150565b5f826115a157634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610f3b57610f3b6113dd565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082028115828204841417610f3b57610f3b6113dd56fea26469706673582212201d19e61504d465ec3ba0180b727a8145b866e802294747dd1c8d24669f7f96f464736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630ef332ca1461004e57806313d97e2c1461007b578063a5d5a0501461008e578063f7a9183e146100a1575b5f80fd5b61006161005c36600461123c565b6100cf565b604080519283526020830191909152015b60405180910390f35b61006161008936600461128a565b61037b565b61006161009c3660046112c8565b61055c565b6100b46100af366004611328565b610811565b60408051938452602084019290925290820152606001610072565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101329190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c91906113b2565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ff9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610245573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061026991906113b2565b9050811580610276575080155b1561028957600d5f935093505050610372565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102ea91906113b2565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918b169063d686e9ee90602401602060405180830381865afa158015610333573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061035791906113b2565b90505f6103678883878787610892565b5f9750955050505050505b94509492505050565b5f805f670de0b6b3a764000090505f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610430573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061045491906113b2565b9050805f0361046b57600d5f935093505050610554565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104cc91906113b2565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918a169063d686e9ee90602401602060405180830381865afa158015610515573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053991906113b2565b90505f6105498883878787610892565b5f9750955050505050505b935093915050565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105bf9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610605573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062991906113b2565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa1580156106d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f691906113b2565b9050811580610703575080155b1561071657600d5f935093505050610807565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610753573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077791906113b2565b60405163afd3783b60e01b81526001600160a01b038c8116600483015289811660248301529192505f918b169063afd3783b90604401602060405180830381865afa1580156107c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ec91906113b2565b90505f6107fc8883878787610892565b5f9750955050505050505b9550959350505050565b5f805f805f6108248b8b8b8b8b8b610904565b91509150815f1461083d575092505f9150819050610886565b60208101518151111561086a575f6020820151825161085c91906113f1565b5f9450945094505050610886565b5f815160208301515f9161087d916113f1565b94509450945050505b96509650969350505050565b5f806108ba604051806020016040528088815250604051806020016040528088815250610efa565b90505f6108e3604051806020016040528087815250604051806020016040528087815250610efa565b90506108f86108f28383610f41565b89610f79565b98975050505050505050565b5f61090d611165565b604051632aff3bff60e21b81526001600160a01b0388811660048301525f91908a169063abfceffc906024015f60405180830381865afa158015610953573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261097a9190810190611428565b80519091505f856001811115610992576109926113c9565b03610a0b57896001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f79190611397565b6001600160a01b0316610160840152610a7b565b896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a47573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6b9190611397565b6001600160a01b03166101808401525b5f5b81811015610df7575f838281518110610a9857610a986114dc565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038d811660048301529192509082169063c37f68e290602401608060405180830381865afa158015610aeb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b0f91906114f0565b60808901526060880152604087015295508515610b3457600f5b955050505050610eef565b6040805160208101918290526319ef3e8b60e01b909152806001600160a01b038e166319ef3e8b610b6a8f868d60248701611523565b602060405180830381865afa158015610b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906113b2565b905260c086015260408051602081019091526080860151815260e08601525f876001811115610bda57610bda6113c9565b03610c9c576101608501516040516388142b6b60e01b81526001600160a01b0383811660048301525f9283929116906388142b6b906024016040805180830381865afa158015610c2c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c509190611565565b91509150815f1480610c60575080155b15610c7457600d9750505050505050610eef565b6040805160208082018352938152610120890152805192830190528152610140860152610d4d565b61018085015160405163fc57d4df60e01b81526001600160a01b0383811660048301529091169063fc57d4df90602401602060405180830381865afa158015610ce7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d0b91906113b2565b60a086018190525f03610d1f57600d610b29565b604080516020808201835260a088018051835261012089019290925282519081019092525181526101408601525b610d6d610d628660c001518760e00151610efa565b866101200151610efa565b610100860181905260408601518651610d87929190610f98565b855261014085015160608601516020870151610da4929190610f98565b60208601526001600160a01b03808b1690821603610dee57610dd08561010001518a8760200151610f98565b60208601819052610140860151610de8918a90610f98565b60208601525b50600101610a7d565b505f8a6001600160a01b0316639254f5e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e35573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e599190611397565b90506001600160a01b03811615610ee8576020840151604051633c617c9160e11b81526001600160a01b038c81166004830152610ee29291908416906378c2f92290602401602060405180830381865afa158015610eb9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610edd91906113b2565b610fc3565b60208501525b5f94505050505b965096945050505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610f2c865f0151865f0151610ff8565b610f369190611587565b905290505b92915050565b60408051602081019091525f81526040518060200160405280610f36610f72865f0151670de0b6b3a7640000610ff8565b8551611039565b5f80610f85848461106b565b9050610f9081611091565b949350505050565b5f80610fa4858561106b565b9050610fb8610fb282611091565b84610fc3565b9150505b9392505050565b5f610fbc8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b8152506110a8565b5f610fbc83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506110ea565b5f610fbc83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525061113a565b60408051602081019091525f81526040518060200160405280610f36855f015185610ff8565b80515f90610f3b90670de0b6b3a764000090611587565b5f806110b484866115a6565b905082858210156110e15760405162461bcd60e51b81526004016110d891906115b9565b60405180910390fd5b50949350505050565b5f8315806110f6575082155b1561110257505f610fbc565b5f61110d84866115ee565b90508361111a8683611587565b1483906110e15760405162461bcd60e51b81526004016110d891906115b9565b5f818361115a5760405162461bcd60e51b81526004016110d891906115b9565b50610f908385611587565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020016111aa60405180602001604052805f81525090565b81526020016111c460405180602001604052805f81525090565b81526020016111de60405180602001604052805f81525090565b81526020016111f860405180602001604052805f81525090565b815260200161121260405180602001604052805f81525090565b81525f6020820181905260409091015290565b6001600160a01b0381168114611239575f80fd5b50565b5f805f806080858703121561124f575f80fd5b843561125a81611225565b9350602085013561126a81611225565b9250604085013561127a81611225565b9396929550929360600135925050565b5f805f6060848603121561129c575f80fd5b83356112a781611225565b925060208401356112b781611225565b929592945050506040919091013590565b5f805f805f60a086880312156112dc575f80fd5b85356112e781611225565b945060208601356112f781611225565b9350604086013561130781611225565b9250606086013561131781611225565b949793965091946080013592915050565b5f805f805f8060c0878903121561133d575f80fd5b863561134881611225565b9550602087013561135881611225565b9450604087013561136881611225565b9350606087013592506080870135915060a087013560028110611389575f80fd5b809150509295509295509295565b5f602082840312156113a7575f80fd5b8151610fbc81611225565b5f602082840312156113c2575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b81810381811115610f3b57610f3b6113dd565b634e487b7160e01b5f52604160045260245ffd5b805161142381611225565b919050565b5f6020808385031215611439575f80fd5b825167ffffffffffffffff80821115611450575f80fd5b818501915085601f830112611463575f80fd5b81518181111561147557611475611404565b8060051b604051601f19603f8301168101818110858211171561149a5761149a611404565b6040529182528482019250838101850191888311156114b7575f80fd5b938501935b828510156108f8576114cd85611418565b845293850193928501926114bc565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215611503575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061155757634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f8060408385031215611576575f80fd5b505080516020909101519092909150565b5f826115a157634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610f3b57610f3b6113dd565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082028115828204841417610f3b57610f3b6113dd56fea26469706673582212201d19e61504d465ec3ba0180b727a8145b866e802294747dd1c8d24669f7f96f464736f6c63430008190033", "devdoc": { "author": "Venus", "events": { diff --git a/deployments/bscmainnet/FlashLoanFacet.json b/deployments/bscmainnet/FlashLoanFacet.json index 3fd08dfcb..e0e233ff5 100644 --- a/deployments/bscmainnet/FlashLoanFacet.json +++ b/deployments/bscmainnet/FlashLoanFacet.json @@ -1,5 +1,5 @@ { - "address": "0x72a284f144F2BE56549573DDFac2A90F8D662ed1", + "address": "0x7F00af2f30a55e79311392C98fBBfA629D19b3A5", "abi": [ { "inputs": [], @@ -560,6 +560,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1199,28 +1212,28 @@ "type": "function" } ], - "transactionHash": "0x9da9b3282392f464d09408c9182d19df56bccd7298f94a9da4bedb45191ad309", + "transactionHash": "0x25316e657291376455229fca1b826ef02f5fea7d4611ec3f68dd065d7132b8c3", "receipt": { "to": null, - "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x72a284f144F2BE56549573DDFac2A90F8D662ed1", - "transactionIndex": 258, - "gasUsed": "1510105", + "from": "0x9b0A3EAE7f174937d31745B710BbeA68e9D1BEf7", + "contractAddress": "0x7F00af2f30a55e79311392C98fBBfA629D19b3A5", + "transactionIndex": 44, + "gasUsed": "1520957", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xca7413b9155aff1fe1e645ef9b29efbef2f539c151a050e884385720aaab82d6", - "transactionHash": "0x9da9b3282392f464d09408c9182d19df56bccd7298f94a9da4bedb45191ad309", + "blockHash": "0xe7dfe6c0fe50f831ab850e1afe276614ef9eb39c4070cd9dd28bdb13a99ffd1f", + "transactionHash": "0x25316e657291376455229fca1b826ef02f5fea7d4611ec3f68dd065d7132b8c3", "logs": [], - "blockNumber": 66295540, - "cumulativeGasUsed": "25438838", + "blockNumber": 95559359, + "cumulativeGasUsed": "13261054", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 2, - "solcInputHash": "7eb14bb68efebde544bca48fc6b525f5", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract VToken[]\",\"name\":\"assets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"FlashLoanExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repaidAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingDebt\",\"type\":\"uint256\"}],\"name\":\"FlashLoanRepaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FLASHLOAN_ASSETS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"underlyingAmounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"param\",\"type\":\"bytes\"}],\"name\":\"executeFlashLoan\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract implements flash loan functionality allowing users to borrow assets temporarily within a single transaction. Users can borrow multiple assets simultaneously and have the flexibility to repay partially, with unpaid balances automatically converted to debt positions. The contract supports protocol fee collection and integrates with the Venus lending protocol.\",\"errors\":{\"ReentrancyGuardReentrantCall()\":[{\"details\":\"Unauthorized reentrant call.\"}]},\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"executeFlashLoan(address,address,address[],uint256[],bytes)\":{\"custom:error\":\"FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.InvalidAmount is thrown if the requested amount is zero.TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.NoAssetsRequested is thrown if no assets are requested for the flash loan.InvalidFlashLoanParams is thrown if the flash loan params are invalid.MarketNotListed is thrown if the specified vToken market is not listed.SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\",\"custom:event\":\"Emits FlashLoanExecuted on success\",\"details\":\"Transfers the specified assets to the receiver contract and handles repayment.\",\"params\":{\"onBehalf\":\"The address of the user whose debt position will be used for the flashLoan.\",\"param\":\"The bytes passed in the executeOperation call.\",\"receiver\":\"The address of the contract that will receive the flashLoan amount and execute the operation.\",\"underlyingAmounts\":\"The amounts of each underlying assets to be loaned.\",\"vTokens\":\"The addresses of the vToken assets to be loaned.\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}}},\"title\":\"FlashLoanFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"FlashLoanExecuted(address,address[],uint256[])\":{\"notice\":\"Emitted when the flash loan is successfully executed\"},\"FlashLoanRepaid(address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when a flash loan is repaid (fully or partially) and shows debt position status\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"}},\"kind\":\"user\",\"methods\":{\"MAX_FLASHLOAN_ASSETS()\":{\"notice\":\"Maximum number of assets that can be flash loaned in a single transaction\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"executeFlashLoan(address,address,address[],uint256[],bytes)\":{\"notice\":\"Executes a flashLoan operation with the requested assets.\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contains all the methods related to flash loans\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol\":\"FlashLoanFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IFlashLoanFacet } from \\\"../interfaces/IFlashLoanFacet.sol\\\";\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { IFlashLoanReceiver } from \\\"../../../FlashLoan/interfaces/IFlashLoanReceiver.sol\\\";\\nimport { ReentrancyGuardTransient } from \\\"../../../Utils/ReentrancyGuardTransient.sol\\\";\\n\\n/**\\n * @title FlashLoanFacet\\n * @author Venus\\n * @notice This facet contains all the methods related to flash loans\\n * @dev This contract implements flash loan functionality allowing users to borrow assets temporarily\\n * within a single transaction. Users can borrow multiple assets simultaneously and have the\\n * flexibility to repay partially, with unpaid balances automatically converted to debt positions.\\n * The contract supports protocol fee collection and integrates with the Venus lending protocol.\\n */\\ncontract FlashLoanFacet is IFlashLoanFacet, FacetBase, ReentrancyGuardTransient {\\n /// @notice Maximum number of assets that can be flash loaned in a single transaction\\n uint256 public constant MAX_FLASHLOAN_ASSETS = 200;\\n\\n /// @notice Emitted when the flash loan is successfully executed\\n event FlashLoanExecuted(address indexed receiver, VToken[] assets, uint256[] amounts);\\n\\n /// @notice Emitted when a flash loan is repaid (fully or partially) and shows debt position status\\n event FlashLoanRepaid(\\n address indexed receiver,\\n address indexed onBehalf,\\n address indexed asset,\\n uint256 repaidAmount,\\n uint256 remainingDebt\\n );\\n\\n /**\\n * @notice Executes a flashLoan operation with the requested assets.\\n * @dev Transfers the specified assets to the receiver contract and handles repayment.\\n * @param onBehalf The address of the user whose debt position will be used for the flashLoan.\\n * @param receiver The address of the contract that will receive the flashLoan amount and execute the operation.\\n * @param vTokens The addresses of the vToken assets to be loaned.\\n * @param underlyingAmounts The amounts of each underlying assets to be loaned.\\n * @param param The bytes passed in the executeOperation call.\\n * @custom:error FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.\\n * @custom:error FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.\\n * @custom:error InvalidAmount is thrown if the requested amount is zero.\\n * @custom:error TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.\\n * @custom:error NoAssetsRequested is thrown if no assets are requested for the flash loan.\\n * @custom:error InvalidFlashLoanParams is thrown if the flash loan params are invalid.\\n * @custom:error MarketNotListed is thrown if the specified vToken market is not listed.\\n * @custom:error SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.\\n * @custom:error NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\\n * @custom:event Emits FlashLoanExecuted on success\\n */\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) external nonReentrant {\\n if (flashLoanPaused) {\\n revert FlashLoanPausedSystemWide();\\n }\\n\\n ensureNonzeroAddress(onBehalf);\\n\\n uint256 len = vTokens.length;\\n Market storage market;\\n\\n // vTokens array must not be empty\\n if (len == 0) {\\n revert NoAssetsRequested();\\n }\\n // Add maximum array length check to prevent gas limit issues\\n if (len > MAX_FLASHLOAN_ASSETS) {\\n revert TooManyAssetsRequested(len, MAX_FLASHLOAN_ASSETS);\\n }\\n\\n // All arrays must have the same length and not be zero\\n if (len != underlyingAmounts.length) {\\n revert InvalidFlashLoanParams();\\n }\\n\\n for (uint256 i; i < len; ++i) {\\n market = getCorePoolMarket(address(vTokens[i]));\\n if (!market.isListed) {\\n revert MarketNotListed(address(vTokens[i]));\\n }\\n if (!(vTokens[i]).isFlashLoanEnabled()) {\\n revert FlashLoanNotEnabled();\\n }\\n if (underlyingAmounts[i] == 0) {\\n revert InvalidAmount();\\n }\\n }\\n\\n ensureNonzeroAddress(receiver);\\n\\n if (!authorizedFlashLoan[msg.sender]) {\\n revert SenderNotAuthorizedForFlashLoan(msg.sender);\\n }\\n\\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\\n revert NotAnApprovedDelegate();\\n }\\n\\n // Execute flash loan phases\\n _executeFlashLoanPhases(onBehalf, receiver, vTokens, underlyingAmounts, param);\\n\\n emit FlashLoanExecuted(receiver, vTokens, underlyingAmounts);\\n }\\n\\n /**\\n * @notice Executes all flash loan phases in sequence\\n * @dev Orchestrates the complete flash loan process through three phases:\\n * Phase 1: Calculate fees and transfer assets to receiver\\n * Phase 2: Execute custom operations on receiver contract\\n * Phase 3: Handle repayment and debt position creation\\n * @param onBehalf The address whose debt position will be used for any unpaid flash loan balance\\n * @param receiver The address of the contract receiving the flash loan\\n * @param vTokens Array of vToken contracts for the assets being borrowed\\n * @param underlyingAmounts Array of amounts being borrowed for each asset\\n * @param param Additional parameters passed to the receiver contract\\n */\\n function _executeFlashLoanPhases(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) internal {\\n FlashLoanFee memory flashLoanData;\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n // Initialize arrays\\n flashLoanData.totalFees = new uint256[](vTokensLength);\\n flashLoanData.protocolFees = new uint256[](vTokensLength);\\n\\n // Phase 1: Calculate fees and transfer assets\\n _executePhase1(receiver, vTokens, underlyingAmounts, flashLoanData);\\n // Phase 2: Execute operations on receiver contract\\n uint256[] memory tokensApproved = _executePhase2(\\n onBehalf,\\n receiver,\\n vTokens,\\n underlyingAmounts,\\n flashLoanData.totalFees,\\n param\\n );\\n // Phase 3: Handles repayment\\n _executePhase3(onBehalf, receiver, vTokens, underlyingAmounts, tokensApproved, flashLoanData);\\n }\\n\\n /**\\n * @notice Phase 1: Calculate fees and transfer assets to receiver\\n * @dev For each requested asset:\\n * - Calculates total fee and protocol fee using the vToken's fee structure\\n * - Transfers the requested amount from the vToken to the receiver\\n * - Updates flash loan tracking in the vToken contract\\n * @param receiver The address receiving the flash loan assets\\n * @param vTokens Array of vToken contracts for the assets being borrowed\\n * @param underlyingAmounts Array of amounts being borrowed for each asset\\n * @param flashLoanData Struct containing fee arrays to be populated\\n */\\n function _executePhase1(\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n FlashLoanFee memory flashLoanData\\n ) internal {\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n (flashLoanData.totalFees[i], flashLoanData.protocolFees[i]) = vTokens[i].calculateFlashLoanFee(\\n underlyingAmounts[i]\\n );\\n\\n // Transfer the asset to receiver\\n vTokens[i].transferOutUnderlyingFlashLoan(receiver, underlyingAmounts[i]);\\n }\\n }\\n\\n /**\\n * @notice Phase 2: Execute custom operations on receiver contract\\n * @dev Calls the receiver contract's executeOperation function, allowing it to perform\\n * custom logic with the borrowed assets. The receiver must return success status\\n * and specify repayment amounts for each asset.\\n * @param onBehalf The address whose debt position will be used for any unpaid balance\\n * @param receiver The address of the contract executing custom operations\\n * @param vTokens Array of vToken contracts for the borrowed assets\\n * @param underlyingAmounts Array of amounts that were borrowed for each asset\\n * @param totalFees Array of total fees for each borrowed asset\\n * @param param Additional parameters passed to the receiver's executeOperation function\\n * @return tokensApproved Array of amounts the receiver approved for repayment\\n * @custom:error ExecuteFlashLoanFailed is thrown if the receiver's executeOperation returns false\\n */\\n function _executePhase2(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n uint256[] memory totalFees,\\n bytes memory param\\n ) internal returns (uint256[] memory) {\\n (bool success, uint256[] memory tokensApproved) = IFlashLoanReceiver(receiver).executeOperation(\\n vTokens,\\n underlyingAmounts,\\n totalFees,\\n msg.sender,\\n onBehalf,\\n param\\n );\\n\\n if (!success) {\\n revert ExecuteFlashLoanFailed();\\n }\\n return tokensApproved;\\n }\\n\\n /**\\n * @notice Phase 3: Handles repayment based on full or partial repayment\\n * @dev Processes repayment for each asset in the flash loan:\\n * - Ensures minimum fee repayment for each asset\\n * - Creates debt positions for any unpaid balances\\n * - Handles protocol fee distribution automatically\\n * @param onBehalf The address whose debt position will be used for any unpaid balance\\n * @param receiver The address providing the repayment\\n * @param vTokens Array of vToken contracts for the borrowed assets\\n * @param underlyingAmounts Array of amounts that were originally borrowed for each asset\\n * @param underlyingAmountsToRepay Array of amounts to be repaid for each asset\\n * @param flashLoanData Struct containing calculated fees for each asset\\n */\\n function _executePhase3(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n uint256[] memory underlyingAmountsToRepay,\\n FlashLoanFee memory flashLoanData\\n ) internal {\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n _handleFlashLoan(\\n vTokens[i],\\n onBehalf,\\n receiver,\\n underlyingAmounts[i],\\n underlyingAmountsToRepay[i],\\n flashLoanData.totalFees[i],\\n flashLoanData.protocolFees[i]\\n );\\n }\\n }\\n\\n /**\\n * @notice Handles the repayment and fee logic for a flash loan.\\n * @dev This function processes flash loan repayment with the following logic:\\n * 1. Ensures the repayment amount is at least equal to the total fee (minimum requirement).\\n * 2. Caps the repayment to prevent over-repayment (borrowedAmount + totalFee maximum).\\n * 3. Transfers the actual repayment amount from the receiver to the vToken.\\n * 4. If repayment is less than the full amount (borrowedAmount + totalFee), creates a debt position\\n * for the unpaid balance on the onBehalf address.\\n * 5. Protocol fees are automatically handled within the transferInUnderlyingFlashLoan function.\\n * @param vToken The vToken contract for the asset being flash loaned.\\n * @param onBehalf The address whose debt position will be used if there is any unpaid flash loan balance.\\n * @param receiver The address that received the flash loan and is providing the repayment.\\n * @param borrowedAmount The original amount that was borrowed (passed from underlyingAmounts).\\n * @param repayAmount The amount being repaid by the receiver (may be partial or full repayment).\\n * @param totalFee The total fee charged for the flash loan (minimum required repayment).\\n * @param protocolFee The portion of the total fee allocated to the protocol.\\n * @custom:error NotEnoughRepayment is thrown if repayAmount is less than the minimum required fee.\\n * @custom:error FailedToCreateDebtPosition is thrown if debt position creation fails for unpaid balance.\\n */\\n function _handleFlashLoan(\\n VToken vToken,\\n address payable onBehalf,\\n address payable receiver,\\n uint256 borrowedAmount,\\n uint256 repayAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) internal {\\n uint256 maxExpectedRepayment = borrowedAmount + totalFee;\\n uint256 actualRepayAmount = repayAmount > maxExpectedRepayment ? maxExpectedRepayment : repayAmount;\\n\\n if (actualRepayAmount < totalFee) {\\n revert NotEnoughRepayment(actualRepayAmount, totalFee);\\n }\\n\\n // Transfer repayment (this will handle the protocol fee as well)\\n uint256 actualAmountTransferred = vToken.transferInUnderlyingFlashLoan(\\n receiver,\\n actualRepayAmount,\\n totalFee,\\n protocolFee\\n );\\n\\n // Default for full repayment\\n uint256 leftUnpaidBalance;\\n\\n if (maxExpectedRepayment > actualAmountTransferred) {\\n // If there is any unpaid balance, it becomes an ongoing debt\\n leftUnpaidBalance = maxExpectedRepayment - actualAmountTransferred;\\n\\n uint256 debtError = vToken.flashLoanDebtPosition(onBehalf, leftUnpaidBalance);\\n if (debtError != 0) {\\n revert FailedToCreateDebtPosition();\\n }\\n }\\n\\n // Emit event for partial repayment with debt position creation\\n emit FlashLoanRepaid(\\n receiver,\\n onBehalf,\\n address(vToken.underlying()),\\n actualAmountTransferred,\\n leftUnpaidBalance\\n );\\n }\\n}\\n\",\"keccak256\":\"0x33aa51b0f084ec8653700c0e69b6464658bfd272bf3b0e4f4ee85e9c0ea01990\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFlashLoanFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IFlashLoanFacet {\\n /// @notice Data structure to hold flash loan related data during execution\\n struct FlashLoanFee {\\n uint256[] totalFees;\\n uint256[] protocolFees;\\n }\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) external;\\n}\\n\",\"keccak256\":\"0xc453824fde5313e97add12d484120817c1d5870ad17795161633d0538c6ee11e\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/FlashLoan/interfaces/IFlashLoanReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../Tokens/VTokens/VToken.sol\\\";\\n\\n/// @title IFlashLoanReceiver\\n/// @notice Interface for flashLoan receiver contract, which executes custom logic with flash-borrowed assets.\\n/// @dev This interface defines the method that must be implemented by any contract wishing to interact with the flashLoan system.\\n/// Contracts must ensure they have the means to repay at least the premium (fee), with any unpaid balance becoming debt.\\ninterface IFlashLoanReceiver {\\n /**\\n * @notice Executes an operation after receiving the flash-borrowed assets.\\n * @dev Implementation of this function must ensure at least the premium (fee) is repaid within the same transaction.\\n * Any unpaid balance (principal + premium - repaid amount) will be added to the onBehalf address's borrow balance.\\n * @param vTokens The vToken contracts corresponding to the flash-borrowed underlying assets.\\n * @param amounts The amounts of each underlying asset that were flash-borrowed.\\n * @param premiums The premiums (fees) associated with each flash-borrowed asset.\\n * @param initiator The address that initiated the flash loan.\\n * @param onBehalf The address of the user whose debt position will be used for any unpaid flash loan balance.\\n * @param param Additional parameters encoded as bytes. These can be used to pass custom data to the receiver contract.\\n * @return success True if the operation succeeds (regardless of repayment amount), false if the operation fails.\\n * @return repayAmounts Array of uint256 representing the amounts to be repaid for each asset. The receiver contract\\n * must approve these amounts to the respective vToken contracts before this function returns.\\n */\\n function executeOperation(\\n VToken[] calldata vTokens,\\n uint256[] calldata amounts,\\n uint256[] calldata premiums,\\n address initiator,\\n address onBehalf,\\n bytes calldata param\\n ) external returns (bool success, uint256[] memory repayAmounts);\\n}\\n\",\"keccak256\":\"0xe8eb540e98551178726f9d2d24e7ae1ab12ab96349c22f7232bacd377a0b33dd\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ReentrancyGuardTransient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)\\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol\\npragma solidity ^0.8.25;\\n\\nimport { TransientSlot } from \\\"./TransientSlot.sol\\\";\\n\\n/**\\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\\n *\\n * NOTE: This variant only works on networks where EIP-1153 is available.\\n *\\n * _Available since v5.1._\\n */\\nabstract contract ReentrancyGuardTransient {\\n using TransientSlot for *;\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.ReentrancyGuard\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\\n\\n /**\\n * @dev Unauthorized reentrant call.\\n */\\n error ReentrancyGuardReentrantCall();\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return REENTRANCY_GUARD_STORAGE.asBoolean().tload();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be NOT_ENTERED\\n if (_reentrancyGuardEntered()) {\\n revert ReentrancyGuardReentrantCall();\\n }\\n\\n // Any calls to nonReentrant after this point will fail\\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\\n }\\n\\n function _nonReentrantAfter() private {\\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\\n }\\n}\\n\",\"keccak256\":\"0xa27ad29257eb609e5d9ab43d3c84e68c7d22e0ea9bd9dbdc012250e7366d9604\",\"license\":\"MIT\"},\"contracts/Utils/TransientSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/TransientSlot.sol\\npragma solidity ^0.8.25;\\n\\n/**\\n * @dev Library for reading and writing value-types to specific transient storage slots.\\n *\\n * Transient slots are often used to store temporary values that are removed after the current transaction.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * * Example reading and writing values using transient storage:\\n * ```solidity\\n * contract Lock {\\n * using TransientSlot for *;\\n *\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\\n *\\n * modifier locked() {\\n * require(!_LOCK_SLOT.asBoolean().tload());\\n *\\n * _LOCK_SLOT.asBoolean().tstore(true);\\n * _;\\n * _LOCK_SLOT.asBoolean().tstore(false);\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\n */\\nlibrary TransientSlot {\\n /**\\n * @dev UDVT that represent a slot holding a address.\\n */\\n type AddressSlot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a AddressSlot.\\n */\\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\\n return AddressSlot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a bool.\\n */\\n type BooleanSlot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a BooleanSlot.\\n */\\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\\n return BooleanSlot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a bytes32.\\n */\\n type Bytes32Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Bytes32Slot.\\n */\\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\\n return Bytes32Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a uint256.\\n */\\n type Uint256Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Uint256Slot.\\n */\\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\\n return Uint256Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a int256.\\n */\\n type Int256Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Int256Slot.\\n */\\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\\n return Int256Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(AddressSlot slot) internal view returns (address value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(AddressSlot slot, address value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(BooleanSlot slot) internal view returns (bool value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(BooleanSlot slot, bool value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Bytes32Slot slot, bytes32 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Uint256Slot slot, uint256 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Int256Slot slot) internal view returns (int256 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Int256Slot slot, int256 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9ce486f12ba619221439564671d06e5d389b7ac1c72f18d0b08a1e26368a2765\",\"license\":\"MIT\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b50611a518061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106102e5575f3560e01c80638c1ac18a11610195578063c5f956af116100e4578063e0f6123d1161009e578063e875544611610079578063e8755446146107bc578063f445d703146107c5578063f851a440146107f2578063fa6331d814610804575f80fd5b8063e0f6123d14610750578063e37d4b7914610772578063e85a2960146107a9575f80fd5b8063c5f956af146106ea578063c7ee005e146106fd578063d3270f9914610710578063d463654c14610723578063dce154491461072a578063dcfbc0c71461073d575f80fd5b8063b2eafc391161014f578063bbb8864a1161012a578063bbb8864a14610683578063bec04f72146106a2578063bf32442d146106ab578063c5b4db55146106bc575f80fd5b8063b2eafc3914610602578063b8324c7c14610615578063bb82aa5e14610670575f80fd5b80638c1ac18a1461057c5780639254f5e51461059e57806394b2294b146105b157806396c99064146105ba5780639bb27d62146105dc578063a657e579146105ef575f80fd5b80634a58443211610251578063719f701b1161020b5780637d172bd5116101e65780637d172bd51461052a5780637dc0d1d01461053d5780637fb8e8cd146105505780638a7dc1651461055d575f80fd5b8063719f701b146104cf57806373769099146104d85780637655138314610518575f80fd5b80634a5844321461044e5780634d99c7761461046d578063517aa0c71461048057806352d84d1e146104885780635544ed9c1461049b5780635dd3fc9d146104b0575f80fd5b806324a3d622116102a257806324a3d622146103bf57806326782247146103d25780632bc7e29e146103e55780634088c73e1461040457806341a18d2c14610411578063425fad581461043b575f80fd5b806302c3bcbb146102e957806304ef9d581461031b57806308e0225c146103245780630db4b4e51461034e57806310b983381461035757806321af456914610394575b5f80fd5b6103086102f73660046113a4565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61030860225481565b6103086103323660046113c6565b601360209081525f928352604080842090915290825290205481565b610308601d5481565b6103846103653660046113c6565b602c60209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610312565b601e546103a7906001600160a01b031681565b6040516001600160a01b039091168152602001610312565b600a546103a7906001600160a01b031681565b6001546103a7906001600160a01b031681565b6103086103f33660046113a4565b60166020525f908152604090205481565b6018546103849060ff1681565b61030861041f3660046113c6565b601260209081525f928352604080842090915290825290205481565b6018546103849062010000900460ff1681565b61030861045c3660046113a4565b601f6020525f908152604090205481565b61030861047b366004611418565b61080d565b61030860c881565b6103a7610496366004611432565b61082e565b6104ae6104a9366004611589565b610856565b005b6103086104be3660046113a4565b602b6020525f908152604090205481565b610308601c5481565b6105006104e63660046113a4565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610312565b60185461038490610100900460ff1681565b601b546103a7906001600160a01b031681565b6004546103a7906001600160a01b031681565b6039546103849060ff1681565b61030861056b3660046113a4565b60146020525f908152604090205481565b61038461058a3660046113a4565b602d6020525f908152604090205460ff1681565b6015546103a7906001600160a01b031681565b61030860075481565b6105cd6105c836600461168e565b610b48565b604051610312939291906116d5565b6025546103a7906001600160a01b031681565b603754610500906001600160601b031681565b6020546103a7906001600160a01b031681565b61064c6106233660046113a4565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610312565b6002546103a7906001600160a01b031681565b6103086106913660046113a4565b602a6020525f908152604090205481565b61030860175481565b6033546001600160a01b03166103a7565b6106d26ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b039091168152602001610312565b6021546103a7906001600160a01b031681565b6031546103a7906001600160a01b031681565b6026546103a7906001600160a01b031681565b6105005f81565b6103a76107383660046116fe565b610bf5565b6003546103a7906001600160a01b031681565b61038461075e3660046113a4565b60386020525f908152604090205460ff1681565b61064c6107803660046113a4565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6103846107b7366004611728565b610c29565b61030860055481565b6103846107d33660046113c6565b603260209081525f928352604080842090915290825290205460ff1681565b5f546103a7906001600160a01b031681565b610308601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d818154811061083d575f80fd5b5f918252602090912001546001600160a01b0316905081565b61085e610c6d565b60395460ff1615610882576040516323118a8360e01b815260040160405180910390fd5b61088b85610cdc565b82515f8181036108ae5760405163bd96af5b60e01b815260040160405180910390fd5b60c88211156108df5760405163d2f1924360e01b81526004810183905260c860248201526044015b60405180910390fd5b835182146109005760405163aa6eb14560e01b815260040160405180910390fd5b5f5b82811015610a525761092c86828151811061091f5761091f611757565b6020026020010151610d2d565b805490925060ff1661097b5785818151811061094a5761094a611757565b6020026020010151604051635a9a1eb960e11b81526004016108d691906001600160a01b0391909116815260200190565b85818151811061098d5761098d611757565b60200260200101516001600160a01b031663ae3fcb1f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f4919061177a565b610a1157604051630a3fad8360e01b815260040160405180910390fd5b848181518110610a2357610a23611757565b60200260200101515f03610a4a5760405163162908e360e11b815260040160405180910390fd5b600101610902565b50610a5c86610cdc565b335f9081526038602052604090205460ff16610a8d576040516319d14ecf60e01b81523360048201526024016108d6565b336001600160a01b03881614801590610ac957506001600160a01b0387165f908152602c6020908152604080832033845290915290205460ff16155b15610ae7576040516337248ad960e01b815260040160405180910390fd5b610af48787878787610d4f565b856001600160a01b03167f785e5057f6e5f2e298f8dce2755a6ef29f9dd8a0f82a8b5cad101ea5ef803f048686604051610b2f929190611805565b60405180910390a25050610b41610e2a565b5050505050565b60366020525f9081526040902080548190610b6290611832565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8e90611832565b8015610bd95780601f10610bb057610100808354040283529160200191610bd9565b820191905f5260205f20905b815481529060010190602001808311610bbc57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6008602052815f5260405f208181548110610c0e575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610c5357610c5361186a565b815260208101919091526040015f205460ff169392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15610cad57604051633ee5aeb560e01b815260040160405180910390fd5b610cda60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90610e54565b565b6001600160a01b038116610d2a5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b60448201526064016108d6565b50565b5f60095f610d3b5f8561080d565b81526020019081526020015f209050919050565b604080518082019091526060808252602082015283518067ffffffffffffffff811115610d7e57610d7e611449565b604051908082528060200260200182016040528015610da7578160200160208202803683370190505b5082528067ffffffffffffffff811115610dc357610dc3611449565b604051908082528060200260200182016040528015610dec578160200160208202803683370190505b506020830152610dfe86868685610e5b565b5f610e1088888888875f015189610ffb565b9050610e208888888885886110a5565b5050505050505050565b610cda5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00610cd4565b80825d5050565b82515f5b81811015610ff357848181518110610e7957610e79611757565b60200260200101516001600160a01b03166371507cd5858381518110610ea157610ea1611757565b60200260200101516040518263ffffffff1660e01b8152600401610ec791815260200190565b6040805180830381865afa158015610ee1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f05919061187e565b8451805184908110610f1957610f19611757565b6020026020010185602001518481518110610f3657610f36611757565b6020026020010182815250828152505050848181518110610f5957610f59611757565b60200260200101516001600160a01b0316638d1f23d487868481518110610f8257610f82611757565b60200260200101516040518363ffffffff1660e01b8152600401610fbb9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b158015610fd2575f80fd5b505af1158015610fe4573d5f803e3d5ffd5b50505050806001019050610e5f565b505050505050565b60605f80876001600160a01b031663fc08f9f6888888338e8a6040518763ffffffff1660e01b8152600401611035969594939291906118a0565b5f604051808303815f875af1158015611050573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110779190810190611910565b915091508161109957604051635a3b2cbb60e11b815260040160405180910390fd5b98975050505050505050565b83515f5b81811015610e20576111448682815181106110c6576110c6611757565b602002602001015189898885815181106110e2576110e2611757565b60200260200101518886815181106110fc576110fc611757565b6020026020010151885f0151878151811061111957611119611757565b60200260200101518960200151888151811061113757611137611757565b602002602001015161114c565b6001016110a9565b5f61115783866119c3565b90505f8185116111675784611169565b815b9050838110156111965760405163bcb60bf360e01b815260048101829052602481018590526044016108d6565b60405163324235c960e11b81526001600160a01b0388811660048301526024820183905260448201869052606482018590525f91908b16906364846b92906084016020604051808303815f875af11580156111f3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061121791906119d6565b90505f818411156112c45761122c82856119ed565b6040516366ce8d7d60e01b81526001600160a01b038c81166004830152602482018390529192505f918d16906366ce8d7d906044016020604051808303815f875af115801561127d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a191906119d6565b905080156112c25760405163ab52b56f60e01b815260040160405180910390fd5b505b8a6001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611300573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113249190611a00565b6001600160a01b03168a6001600160a01b03168a6001600160a01b03167f499433c603d8d6db664daa76d7158679cc9f90c4c30723e29495a8c39302a173858560405161137b929190918252602082015260400190565b60405180910390a45050505050505050505050565b6001600160a01b0381168114610d2a575f80fd5b5f602082840312156113b4575f80fd5b81356113bf81611390565b9392505050565b5f80604083850312156113d7575f80fd5b82356113e281611390565b915060208301356113f281611390565b809150509250929050565b80356001600160601b0381168114611413575f80fd5b919050565b5f8060408385031215611429575f80fd5b6113e2836113fd565b5f60208284031215611442575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561148657611486611449565b604052919050565b5f67ffffffffffffffff8211156114a7576114a7611449565b5060051b60200190565b5f82601f8301126114c0575f80fd5b813560206114d56114d08361148e565b61145d565b8083825260208201915060208460051b8701019350868411156114f6575f80fd5b602086015b8481101561151257803583529183019183016114fb565b509695505050505050565b5f82601f83011261152c575f80fd5b813567ffffffffffffffff81111561154657611546611449565b611559601f8201601f191660200161145d565b81815284602083860101111561156d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a0868803121561159d575f80fd5b85356115a881611390565b94506020868101356115b981611390565b9450604087013567ffffffffffffffff808211156115d5575f80fd5b818901915089601f8301126115e8575f80fd5b81356115f66114d08261148e565b81815260059190911b8301840190848101908c831115611614575f80fd5b938501935b8285101561163b57843561162c81611390565b82529385019390850190611619565b975050506060890135925080831115611652575f80fd5b61165e8a848b016114b1565b94506080890135925080831115611673575f80fd5b50506116818882890161151d565b9150509295509295909350565b5f6020828403121561169e575f80fd5b6113bf826113fd565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6116e760608301866116a7565b931515602083015250901515604090910152919050565b5f806040838503121561170f575f80fd5b823561171a81611390565b946020939093013593505050565b5f8060408385031215611739575f80fd5b823561174481611390565b91506020830135600981106113f2575f80fd5b634e487b7160e01b5f52603260045260245ffd5b80518015158114611413575f80fd5b5f6020828403121561178a575f80fd5b6113bf8261176b565b5f815180845260208085019450602084015f5b838110156117cb5781516001600160a01b0316875295820195908201906001016117a6565b509495945050505050565b5f815180845260208085019450602084015f5b838110156117cb578151875295820195908201906001016117e9565b604081525f6118176040830185611793565b828103602084015261182981856117d6565b95945050505050565b600181811c9082168061184657607f821691505b60208210810361186457634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f806040838503121561188f575f80fd5b505080516020909101519092909150565b60c081525f6118b260c0830189611793565b82810360208401526118c481896117d6565b905082810360408401526118d881886117d6565b6001600160a01b0387811660608601528616608085015283810360a0850152905061190381856116a7565b9998505050505050505050565b5f8060408385031215611921575f80fd5b61192a8361176b565b915060208084015167ffffffffffffffff811115611946575f80fd5b8401601f81018613611956575f80fd5b80516119646114d08261148e565b81815260059190911b82018301908381019088831115611982575f80fd5b928401925b828410156119a057835182529284019290840190611987565b80955050505050509250929050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610828576108286119af565b5f602082840312156119e6575f80fd5b5051919050565b81810381811115610828576108286119af565b5f60208284031215611a10575f80fd5b81516113bf8161139056fea26469706673582212209cd3d81fb9d10e151925b12baabec95e8edecb883076621e2c24c076ac8c649a64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102e5575f3560e01c80638c1ac18a11610195578063c5f956af116100e4578063e0f6123d1161009e578063e875544611610079578063e8755446146107bc578063f445d703146107c5578063f851a440146107f2578063fa6331d814610804575f80fd5b8063e0f6123d14610750578063e37d4b7914610772578063e85a2960146107a9575f80fd5b8063c5f956af146106ea578063c7ee005e146106fd578063d3270f9914610710578063d463654c14610723578063dce154491461072a578063dcfbc0c71461073d575f80fd5b8063b2eafc391161014f578063bbb8864a1161012a578063bbb8864a14610683578063bec04f72146106a2578063bf32442d146106ab578063c5b4db55146106bc575f80fd5b8063b2eafc3914610602578063b8324c7c14610615578063bb82aa5e14610670575f80fd5b80638c1ac18a1461057c5780639254f5e51461059e57806394b2294b146105b157806396c99064146105ba5780639bb27d62146105dc578063a657e579146105ef575f80fd5b80634a58443211610251578063719f701b1161020b5780637d172bd5116101e65780637d172bd51461052a5780637dc0d1d01461053d5780637fb8e8cd146105505780638a7dc1651461055d575f80fd5b8063719f701b146104cf57806373769099146104d85780637655138314610518575f80fd5b80634a5844321461044e5780634d99c7761461046d578063517aa0c71461048057806352d84d1e146104885780635544ed9c1461049b5780635dd3fc9d146104b0575f80fd5b806324a3d622116102a257806324a3d622146103bf57806326782247146103d25780632bc7e29e146103e55780634088c73e1461040457806341a18d2c14610411578063425fad581461043b575f80fd5b806302c3bcbb146102e957806304ef9d581461031b57806308e0225c146103245780630db4b4e51461034e57806310b983381461035757806321af456914610394575b5f80fd5b6103086102f73660046113a4565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61030860225481565b6103086103323660046113c6565b601360209081525f928352604080842090915290825290205481565b610308601d5481565b6103846103653660046113c6565b602c60209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610312565b601e546103a7906001600160a01b031681565b6040516001600160a01b039091168152602001610312565b600a546103a7906001600160a01b031681565b6001546103a7906001600160a01b031681565b6103086103f33660046113a4565b60166020525f908152604090205481565b6018546103849060ff1681565b61030861041f3660046113c6565b601260209081525f928352604080842090915290825290205481565b6018546103849062010000900460ff1681565b61030861045c3660046113a4565b601f6020525f908152604090205481565b61030861047b366004611418565b61080d565b61030860c881565b6103a7610496366004611432565b61082e565b6104ae6104a9366004611589565b610856565b005b6103086104be3660046113a4565b602b6020525f908152604090205481565b610308601c5481565b6105006104e63660046113a4565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610312565b60185461038490610100900460ff1681565b601b546103a7906001600160a01b031681565b6004546103a7906001600160a01b031681565b6039546103849060ff1681565b61030861056b3660046113a4565b60146020525f908152604090205481565b61038461058a3660046113a4565b602d6020525f908152604090205460ff1681565b6015546103a7906001600160a01b031681565b61030860075481565b6105cd6105c836600461168e565b610b48565b604051610312939291906116d5565b6025546103a7906001600160a01b031681565b603754610500906001600160601b031681565b6020546103a7906001600160a01b031681565b61064c6106233660046113a4565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610312565b6002546103a7906001600160a01b031681565b6103086106913660046113a4565b602a6020525f908152604090205481565b61030860175481565b6033546001600160a01b03166103a7565b6106d26ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b039091168152602001610312565b6021546103a7906001600160a01b031681565b6031546103a7906001600160a01b031681565b6026546103a7906001600160a01b031681565b6105005f81565b6103a76107383660046116fe565b610bf5565b6003546103a7906001600160a01b031681565b61038461075e3660046113a4565b60386020525f908152604090205460ff1681565b61064c6107803660046113a4565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6103846107b7366004611728565b610c29565b61030860055481565b6103846107d33660046113c6565b603260209081525f928352604080842090915290825290205460ff1681565b5f546103a7906001600160a01b031681565b610308601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d818154811061083d575f80fd5b5f918252602090912001546001600160a01b0316905081565b61085e610c6d565b60395460ff1615610882576040516323118a8360e01b815260040160405180910390fd5b61088b85610cdc565b82515f8181036108ae5760405163bd96af5b60e01b815260040160405180910390fd5b60c88211156108df5760405163d2f1924360e01b81526004810183905260c860248201526044015b60405180910390fd5b835182146109005760405163aa6eb14560e01b815260040160405180910390fd5b5f5b82811015610a525761092c86828151811061091f5761091f611757565b6020026020010151610d2d565b805490925060ff1661097b5785818151811061094a5761094a611757565b6020026020010151604051635a9a1eb960e11b81526004016108d691906001600160a01b0391909116815260200190565b85818151811061098d5761098d611757565b60200260200101516001600160a01b031663ae3fcb1f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f4919061177a565b610a1157604051630a3fad8360e01b815260040160405180910390fd5b848181518110610a2357610a23611757565b60200260200101515f03610a4a5760405163162908e360e11b815260040160405180910390fd5b600101610902565b50610a5c86610cdc565b335f9081526038602052604090205460ff16610a8d576040516319d14ecf60e01b81523360048201526024016108d6565b336001600160a01b03881614801590610ac957506001600160a01b0387165f908152602c6020908152604080832033845290915290205460ff16155b15610ae7576040516337248ad960e01b815260040160405180910390fd5b610af48787878787610d4f565b856001600160a01b03167f785e5057f6e5f2e298f8dce2755a6ef29f9dd8a0f82a8b5cad101ea5ef803f048686604051610b2f929190611805565b60405180910390a25050610b41610e2a565b5050505050565b60366020525f9081526040902080548190610b6290611832565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8e90611832565b8015610bd95780601f10610bb057610100808354040283529160200191610bd9565b820191905f5260205f20905b815481529060010190602001808311610bbc57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6008602052815f5260405f208181548110610c0e575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610c5357610c5361186a565b815260208101919091526040015f205460ff169392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15610cad57604051633ee5aeb560e01b815260040160405180910390fd5b610cda60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90610e54565b565b6001600160a01b038116610d2a5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b60448201526064016108d6565b50565b5f60095f610d3b5f8561080d565b81526020019081526020015f209050919050565b604080518082019091526060808252602082015283518067ffffffffffffffff811115610d7e57610d7e611449565b604051908082528060200260200182016040528015610da7578160200160208202803683370190505b5082528067ffffffffffffffff811115610dc357610dc3611449565b604051908082528060200260200182016040528015610dec578160200160208202803683370190505b506020830152610dfe86868685610e5b565b5f610e1088888888875f015189610ffb565b9050610e208888888885886110a5565b5050505050505050565b610cda5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00610cd4565b80825d5050565b82515f5b81811015610ff357848181518110610e7957610e79611757565b60200260200101516001600160a01b03166371507cd5858381518110610ea157610ea1611757565b60200260200101516040518263ffffffff1660e01b8152600401610ec791815260200190565b6040805180830381865afa158015610ee1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f05919061187e565b8451805184908110610f1957610f19611757565b6020026020010185602001518481518110610f3657610f36611757565b6020026020010182815250828152505050848181518110610f5957610f59611757565b60200260200101516001600160a01b0316638d1f23d487868481518110610f8257610f82611757565b60200260200101516040518363ffffffff1660e01b8152600401610fbb9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b158015610fd2575f80fd5b505af1158015610fe4573d5f803e3d5ffd5b50505050806001019050610e5f565b505050505050565b60605f80876001600160a01b031663fc08f9f6888888338e8a6040518763ffffffff1660e01b8152600401611035969594939291906118a0565b5f604051808303815f875af1158015611050573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110779190810190611910565b915091508161109957604051635a3b2cbb60e11b815260040160405180910390fd5b98975050505050505050565b83515f5b81811015610e20576111448682815181106110c6576110c6611757565b602002602001015189898885815181106110e2576110e2611757565b60200260200101518886815181106110fc576110fc611757565b6020026020010151885f0151878151811061111957611119611757565b60200260200101518960200151888151811061113757611137611757565b602002602001015161114c565b6001016110a9565b5f61115783866119c3565b90505f8185116111675784611169565b815b9050838110156111965760405163bcb60bf360e01b815260048101829052602481018590526044016108d6565b60405163324235c960e11b81526001600160a01b0388811660048301526024820183905260448201869052606482018590525f91908b16906364846b92906084016020604051808303815f875af11580156111f3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061121791906119d6565b90505f818411156112c45761122c82856119ed565b6040516366ce8d7d60e01b81526001600160a01b038c81166004830152602482018390529192505f918d16906366ce8d7d906044016020604051808303815f875af115801561127d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a191906119d6565b905080156112c25760405163ab52b56f60e01b815260040160405180910390fd5b505b8a6001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611300573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113249190611a00565b6001600160a01b03168a6001600160a01b03168a6001600160a01b03167f499433c603d8d6db664daa76d7158679cc9f90c4c30723e29495a8c39302a173858560405161137b929190918252602082015260400190565b60405180910390a45050505050505050505050565b6001600160a01b0381168114610d2a575f80fd5b5f602082840312156113b4575f80fd5b81356113bf81611390565b9392505050565b5f80604083850312156113d7575f80fd5b82356113e281611390565b915060208301356113f281611390565b809150509250929050565b80356001600160601b0381168114611413575f80fd5b919050565b5f8060408385031215611429575f80fd5b6113e2836113fd565b5f60208284031215611442575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561148657611486611449565b604052919050565b5f67ffffffffffffffff8211156114a7576114a7611449565b5060051b60200190565b5f82601f8301126114c0575f80fd5b813560206114d56114d08361148e565b61145d565b8083825260208201915060208460051b8701019350868411156114f6575f80fd5b602086015b8481101561151257803583529183019183016114fb565b509695505050505050565b5f82601f83011261152c575f80fd5b813567ffffffffffffffff81111561154657611546611449565b611559601f8201601f191660200161145d565b81815284602083860101111561156d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a0868803121561159d575f80fd5b85356115a881611390565b94506020868101356115b981611390565b9450604087013567ffffffffffffffff808211156115d5575f80fd5b818901915089601f8301126115e8575f80fd5b81356115f66114d08261148e565b81815260059190911b8301840190848101908c831115611614575f80fd5b938501935b8285101561163b57843561162c81611390565b82529385019390850190611619565b975050506060890135925080831115611652575f80fd5b61165e8a848b016114b1565b94506080890135925080831115611673575f80fd5b50506116818882890161151d565b9150509295509295909350565b5f6020828403121561169e575f80fd5b6113bf826113fd565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6116e760608301866116a7565b931515602083015250901515604090910152919050565b5f806040838503121561170f575f80fd5b823561171a81611390565b946020939093013593505050565b5f8060408385031215611739575f80fd5b823561174481611390565b91506020830135600981106113f2575f80fd5b634e487b7160e01b5f52603260045260245ffd5b80518015158114611413575f80fd5b5f6020828403121561178a575f80fd5b6113bf8261176b565b5f815180845260208085019450602084015f5b838110156117cb5781516001600160a01b0316875295820195908201906001016117a6565b509495945050505050565b5f815180845260208085019450602084015f5b838110156117cb578151875295820195908201906001016117e9565b604081525f6118176040830185611793565b828103602084015261182981856117d6565b95945050505050565b600181811c9082168061184657607f821691505b60208210810361186457634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f806040838503121561188f575f80fd5b505080516020909101519092909150565b60c081525f6118b260c0830189611793565b82810360208401526118c481896117d6565b905082810360408401526118d881886117d6565b6001600160a01b0387811660608601528616608085015283810360a0850152905061190381856116a7565b9998505050505050505050565b5f8060408385031215611921575f80fd5b61192a8361176b565b915060208084015167ffffffffffffffff811115611946575f80fd5b8401601f81018613611956575f80fd5b80516119646114d08261148e565b81815260059190911b82018301908381019088831115611982575f80fd5b928401925b828410156119a057835182529284019290840190611987565b80955050505050509250929050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610828576108286119af565b5f602082840312156119e6575f80fd5b5051919050565b81810381811115610828576108286119af565b5f60208284031215611a10575f80fd5b81516113bf8161139056fea26469706673582212209cd3d81fb9d10e151925b12baabec95e8edecb883076621e2c24c076ac8c649a64736f6c63430008190033", + "numDeployments": 3, + "solcInputHash": "cbc4287e135101fe4c78448d0f5f2ecc", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract VToken[]\",\"name\":\"assets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"FlashLoanExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repaidAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingDebt\",\"type\":\"uint256\"}],\"name\":\"FlashLoanRepaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FLASHLOAN_ASSETS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"underlyingAmounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"param\",\"type\":\"bytes\"}],\"name\":\"executeFlashLoan\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract implements flash loan functionality allowing users to borrow assets temporarily within a single transaction. Users can borrow multiple assets simultaneously and have the flexibility to repay partially, with unpaid balances automatically converted to debt positions. The contract supports protocol fee collection and integrates with the Venus lending protocol.\",\"errors\":{\"ReentrancyGuardReentrantCall()\":[{\"details\":\"Unauthorized reentrant call.\"}]},\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"executeFlashLoan(address,address,address[],uint256[],bytes)\":{\"custom:error\":\"FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.InvalidAmount is thrown if the requested amount is zero.TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.NoAssetsRequested is thrown if no assets are requested for the flash loan.InvalidFlashLoanParams is thrown if the flash loan params are invalid.MarketNotListed is thrown if the specified vToken market is not listed.SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\",\"custom:event\":\"Emits FlashLoanExecuted on success\",\"details\":\"Transfers the specified assets to the receiver contract and handles repayment.\",\"params\":{\"onBehalf\":\"The address of the user whose debt position will be used for the flashLoan.\",\"param\":\"The bytes passed in the executeOperation call.\",\"receiver\":\"The address of the contract that will receive the flashLoan amount and execute the operation.\",\"underlyingAmounts\":\"The amounts of each underlying assets to be loaned.\",\"vTokens\":\"The addresses of the vToken assets to be loaned.\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}}},\"title\":\"FlashLoanFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"FlashLoanExecuted(address,address[],uint256[])\":{\"notice\":\"Emitted when the flash loan is successfully executed\"},\"FlashLoanRepaid(address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when a flash loan is repaid (fully or partially) and shows debt position status\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"}},\"kind\":\"user\",\"methods\":{\"MAX_FLASHLOAN_ASSETS()\":{\"notice\":\"Maximum number of assets that can be flash loaned in a single transaction\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"executeFlashLoan(address,address,address[],uint256[],bytes)\":{\"notice\":\"Executes a flashLoan operation with the requested assets.\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contains all the methods related to flash loans\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol\":\"FlashLoanFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\\n enum KeeperAction {\\n SetMinPrice,\\n SetMaxPrice,\\n ExitProtectionMode\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool cachingEnabled;\\n }\\n\\n /// @notice One item in an syncPriceBoundsAndProtections payload\\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\\n struct KeeperActionItem {\\n address asset;\\n KeeperAction action;\\n uint256 value;\\n }\\n\\n /// @notice One item in a setTokenConfigs payload\\n struct TokenConfigInput {\\n /// @notice The underlying asset address\\n address asset;\\n /// @notice Minimum time protection stays active after the last trigger (seconds)\\n uint64 cooldownPeriod;\\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\\n uint256 triggerThreshold;\\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\\n uint256 resetThreshold;\\n /// @notice Whether to enable bounded pricing immediately upon initialization\\n bool enableBoundedPricing;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool enableCaching;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n /// @notice Emitted when the per-asset transient caching flag is toggled\\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\\n error InvalidKeeperAction(uint8 action);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage. The transient\\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n /**\\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\\n * Empty `actions` is a no-op success.\\n * @param actions The list of keeper actions to apply\\n * @custom:access Only authorized keeper addresses\\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\\n */\\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param tokenConfig_ Token config input for the asset\\n * @custom:access Only Governance\\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param tokenConfigs_ Array of token config inputs, one per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if the input array is empty\\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\\n * @custom:error VAINotAllowed if any asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n /**\\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\\n * live spot instead of reading or writing the transient slots. The initial value is\\n * set via the `enableCaching` argument of `setTokenConfig`.\\n * @param asset The underlying asset address\\n * @param enabled Whether transient caching is enabled for this asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CachingEnabledUpdated\\n */\\n function setCachingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold,\\n bool cachingEnabled\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0xe223d88c17c0d752fdb33fa223b63ce124a798512f3d69f3800e9508e7dff931\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IFlashLoanFacet } from \\\"../interfaces/IFlashLoanFacet.sol\\\";\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { IFlashLoanReceiver } from \\\"../../../FlashLoan/interfaces/IFlashLoanReceiver.sol\\\";\\nimport { ReentrancyGuardTransient } from \\\"../../../Utils/ReentrancyGuardTransient.sol\\\";\\n\\n/**\\n * @title FlashLoanFacet\\n * @author Venus\\n * @notice This facet contains all the methods related to flash loans\\n * @dev This contract implements flash loan functionality allowing users to borrow assets temporarily\\n * within a single transaction. Users can borrow multiple assets simultaneously and have the\\n * flexibility to repay partially, with unpaid balances automatically converted to debt positions.\\n * The contract supports protocol fee collection and integrates with the Venus lending protocol.\\n */\\ncontract FlashLoanFacet is IFlashLoanFacet, FacetBase, ReentrancyGuardTransient {\\n /// @notice Maximum number of assets that can be flash loaned in a single transaction\\n uint256 public constant MAX_FLASHLOAN_ASSETS = 200;\\n\\n /// @notice Emitted when the flash loan is successfully executed\\n event FlashLoanExecuted(address indexed receiver, VToken[] assets, uint256[] amounts);\\n\\n /// @notice Emitted when a flash loan is repaid (fully or partially) and shows debt position status\\n event FlashLoanRepaid(\\n address indexed receiver,\\n address indexed onBehalf,\\n address indexed asset,\\n uint256 repaidAmount,\\n uint256 remainingDebt\\n );\\n\\n /**\\n * @notice Executes a flashLoan operation with the requested assets.\\n * @dev Transfers the specified assets to the receiver contract and handles repayment.\\n * @param onBehalf The address of the user whose debt position will be used for the flashLoan.\\n * @param receiver The address of the contract that will receive the flashLoan amount and execute the operation.\\n * @param vTokens The addresses of the vToken assets to be loaned.\\n * @param underlyingAmounts The amounts of each underlying assets to be loaned.\\n * @param param The bytes passed in the executeOperation call.\\n * @custom:error FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.\\n * @custom:error FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.\\n * @custom:error InvalidAmount is thrown if the requested amount is zero.\\n * @custom:error TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.\\n * @custom:error NoAssetsRequested is thrown if no assets are requested for the flash loan.\\n * @custom:error InvalidFlashLoanParams is thrown if the flash loan params are invalid.\\n * @custom:error MarketNotListed is thrown if the specified vToken market is not listed.\\n * @custom:error SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.\\n * @custom:error NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\\n * @custom:event Emits FlashLoanExecuted on success\\n */\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) external nonReentrant {\\n if (flashLoanPaused) {\\n revert FlashLoanPausedSystemWide();\\n }\\n\\n ensureNonzeroAddress(onBehalf);\\n\\n uint256 len = vTokens.length;\\n Market storage market;\\n\\n // vTokens array must not be empty\\n if (len == 0) {\\n revert NoAssetsRequested();\\n }\\n // Add maximum array length check to prevent gas limit issues\\n if (len > MAX_FLASHLOAN_ASSETS) {\\n revert TooManyAssetsRequested(len, MAX_FLASHLOAN_ASSETS);\\n }\\n\\n // All arrays must have the same length and not be zero\\n if (len != underlyingAmounts.length) {\\n revert InvalidFlashLoanParams();\\n }\\n\\n for (uint256 i; i < len; ++i) {\\n market = getCorePoolMarket(address(vTokens[i]));\\n if (!market.isListed) {\\n revert MarketNotListed(address(vTokens[i]));\\n }\\n if (!(vTokens[i]).isFlashLoanEnabled()) {\\n revert FlashLoanNotEnabled();\\n }\\n if (underlyingAmounts[i] == 0) {\\n revert InvalidAmount();\\n }\\n }\\n\\n ensureNonzeroAddress(receiver);\\n\\n if (!authorizedFlashLoan[msg.sender]) {\\n revert SenderNotAuthorizedForFlashLoan(msg.sender);\\n }\\n\\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\\n revert NotAnApprovedDelegate();\\n }\\n\\n // Execute flash loan phases\\n _executeFlashLoanPhases(onBehalf, receiver, vTokens, underlyingAmounts, param);\\n\\n emit FlashLoanExecuted(receiver, vTokens, underlyingAmounts);\\n }\\n\\n /**\\n * @notice Executes all flash loan phases in sequence\\n * @dev Orchestrates the complete flash loan process through three phases:\\n * Phase 1: Calculate fees and transfer assets to receiver\\n * Phase 2: Execute custom operations on receiver contract\\n * Phase 3: Handle repayment and debt position creation\\n * @param onBehalf The address whose debt position will be used for any unpaid flash loan balance\\n * @param receiver The address of the contract receiving the flash loan\\n * @param vTokens Array of vToken contracts for the assets being borrowed\\n * @param underlyingAmounts Array of amounts being borrowed for each asset\\n * @param param Additional parameters passed to the receiver contract\\n */\\n function _executeFlashLoanPhases(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) internal {\\n FlashLoanFee memory flashLoanData;\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n // Initialize arrays\\n flashLoanData.totalFees = new uint256[](vTokensLength);\\n flashLoanData.protocolFees = new uint256[](vTokensLength);\\n\\n // Phase 1: Calculate fees and transfer assets\\n _executePhase1(receiver, vTokens, underlyingAmounts, flashLoanData);\\n // Phase 2: Execute operations on receiver contract\\n uint256[] memory tokensApproved = _executePhase2(\\n onBehalf,\\n receiver,\\n vTokens,\\n underlyingAmounts,\\n flashLoanData.totalFees,\\n param\\n );\\n // Phase 3: Handles repayment\\n _executePhase3(onBehalf, receiver, vTokens, underlyingAmounts, tokensApproved, flashLoanData);\\n }\\n\\n /**\\n * @notice Phase 1: Calculate fees and transfer assets to receiver\\n * @dev For each requested asset:\\n * - Calculates total fee and protocol fee using the vToken's fee structure\\n * - Transfers the requested amount from the vToken to the receiver\\n * - Updates flash loan tracking in the vToken contract\\n * @param receiver The address receiving the flash loan assets\\n * @param vTokens Array of vToken contracts for the assets being borrowed\\n * @param underlyingAmounts Array of amounts being borrowed for each asset\\n * @param flashLoanData Struct containing fee arrays to be populated\\n */\\n function _executePhase1(\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n FlashLoanFee memory flashLoanData\\n ) internal {\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n (flashLoanData.totalFees[i], flashLoanData.protocolFees[i]) = vTokens[i].calculateFlashLoanFee(\\n underlyingAmounts[i]\\n );\\n\\n // Transfer the asset to receiver\\n vTokens[i].transferOutUnderlyingFlashLoan(receiver, underlyingAmounts[i]);\\n }\\n }\\n\\n /**\\n * @notice Phase 2: Execute custom operations on receiver contract\\n * @dev Calls the receiver contract's executeOperation function, allowing it to perform\\n * custom logic with the borrowed assets. The receiver must return success status\\n * and specify repayment amounts for each asset.\\n * @param onBehalf The address whose debt position will be used for any unpaid balance\\n * @param receiver The address of the contract executing custom operations\\n * @param vTokens Array of vToken contracts for the borrowed assets\\n * @param underlyingAmounts Array of amounts that were borrowed for each asset\\n * @param totalFees Array of total fees for each borrowed asset\\n * @param param Additional parameters passed to the receiver's executeOperation function\\n * @return tokensApproved Array of amounts the receiver approved for repayment\\n * @custom:error ExecuteFlashLoanFailed is thrown if the receiver's executeOperation returns false\\n */\\n function _executePhase2(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n uint256[] memory totalFees,\\n bytes memory param\\n ) internal returns (uint256[] memory) {\\n (bool success, uint256[] memory tokensApproved) = IFlashLoanReceiver(receiver).executeOperation(\\n vTokens,\\n underlyingAmounts,\\n totalFees,\\n msg.sender,\\n onBehalf,\\n param\\n );\\n\\n if (!success) {\\n revert ExecuteFlashLoanFailed();\\n }\\n return tokensApproved;\\n }\\n\\n /**\\n * @notice Phase 3: Handles repayment based on full or partial repayment\\n * @dev Processes repayment for each asset in the flash loan:\\n * - Ensures minimum fee repayment for each asset\\n * - Creates debt positions for any unpaid balances\\n * - Handles protocol fee distribution automatically\\n * @param onBehalf The address whose debt position will be used for any unpaid balance\\n * @param receiver The address providing the repayment\\n * @param vTokens Array of vToken contracts for the borrowed assets\\n * @param underlyingAmounts Array of amounts that were originally borrowed for each asset\\n * @param underlyingAmountsToRepay Array of amounts to be repaid for each asset\\n * @param flashLoanData Struct containing calculated fees for each asset\\n */\\n function _executePhase3(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n uint256[] memory underlyingAmountsToRepay,\\n FlashLoanFee memory flashLoanData\\n ) internal {\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n _handleFlashLoan(\\n vTokens[i],\\n onBehalf,\\n receiver,\\n underlyingAmounts[i],\\n underlyingAmountsToRepay[i],\\n flashLoanData.totalFees[i],\\n flashLoanData.protocolFees[i]\\n );\\n }\\n }\\n\\n /**\\n * @notice Handles the repayment and fee logic for a flash loan.\\n * @dev This function processes flash loan repayment with the following logic:\\n * 1. Ensures the repayment amount is at least equal to the total fee (minimum requirement).\\n * 2. Caps the repayment to prevent over-repayment (borrowedAmount + totalFee maximum).\\n * 3. Transfers the actual repayment amount from the receiver to the vToken.\\n * 4. If repayment is less than the full amount (borrowedAmount + totalFee), creates a debt position\\n * for the unpaid balance on the onBehalf address.\\n * 5. Protocol fees are automatically handled within the transferInUnderlyingFlashLoan function.\\n * @param vToken The vToken contract for the asset being flash loaned.\\n * @param onBehalf The address whose debt position will be used if there is any unpaid flash loan balance.\\n * @param receiver The address that received the flash loan and is providing the repayment.\\n * @param borrowedAmount The original amount that was borrowed (passed from underlyingAmounts).\\n * @param repayAmount The amount being repaid by the receiver (may be partial or full repayment).\\n * @param totalFee The total fee charged for the flash loan (minimum required repayment).\\n * @param protocolFee The portion of the total fee allocated to the protocol.\\n * @custom:error NotEnoughRepayment is thrown if repayAmount is less than the minimum required fee.\\n * @custom:error FailedToCreateDebtPosition is thrown if debt position creation fails for unpaid balance.\\n */\\n function _handleFlashLoan(\\n VToken vToken,\\n address payable onBehalf,\\n address payable receiver,\\n uint256 borrowedAmount,\\n uint256 repayAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) internal {\\n uint256 maxExpectedRepayment = borrowedAmount + totalFee;\\n uint256 actualRepayAmount = repayAmount > maxExpectedRepayment ? maxExpectedRepayment : repayAmount;\\n\\n if (actualRepayAmount < totalFee) {\\n revert NotEnoughRepayment(actualRepayAmount, totalFee);\\n }\\n\\n // Transfer repayment (this will handle the protocol fee as well)\\n uint256 actualAmountTransferred = vToken.transferInUnderlyingFlashLoan(\\n receiver,\\n actualRepayAmount,\\n totalFee,\\n protocolFee\\n );\\n\\n // Default for full repayment\\n uint256 leftUnpaidBalance;\\n\\n if (maxExpectedRepayment > actualAmountTransferred) {\\n // If there is any unpaid balance, it becomes an ongoing debt\\n leftUnpaidBalance = maxExpectedRepayment - actualAmountTransferred;\\n\\n uint256 debtError = vToken.flashLoanDebtPosition(onBehalf, leftUnpaidBalance);\\n if (debtError != 0) {\\n revert FailedToCreateDebtPosition();\\n }\\n }\\n\\n // Emit event for partial repayment with debt position creation\\n emit FlashLoanRepaid(\\n receiver,\\n onBehalf,\\n address(vToken.underlying()),\\n actualAmountTransferred,\\n leftUnpaidBalance\\n );\\n }\\n}\\n\",\"keccak256\":\"0x33aa51b0f084ec8653700c0e69b6464658bfd272bf3b0e4f4ee85e9c0ea01990\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFlashLoanFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IFlashLoanFacet {\\n /// @notice Data structure to hold flash loan related data during execution\\n struct FlashLoanFee {\\n uint256[] totalFees;\\n uint256[] protocolFees;\\n }\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) external;\\n}\\n\",\"keccak256\":\"0xc453824fde5313e97add12d484120817c1d5870ad17795161633d0538c6ee11e\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/FlashLoan/interfaces/IFlashLoanReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../Tokens/VTokens/VToken.sol\\\";\\n\\n/// @title IFlashLoanReceiver\\n/// @notice Interface for flashLoan receiver contract, which executes custom logic with flash-borrowed assets.\\n/// @dev This interface defines the method that must be implemented by any contract wishing to interact with the flashLoan system.\\n/// Contracts must ensure they have the means to repay at least the premium (fee), with any unpaid balance becoming debt.\\ninterface IFlashLoanReceiver {\\n /**\\n * @notice Executes an operation after receiving the flash-borrowed assets.\\n * @dev Implementation of this function must ensure at least the premium (fee) is repaid within the same transaction.\\n * Any unpaid balance (principal + premium - repaid amount) will be added to the onBehalf address's borrow balance.\\n * @param vTokens The vToken contracts corresponding to the flash-borrowed underlying assets.\\n * @param amounts The amounts of each underlying asset that were flash-borrowed.\\n * @param premiums The premiums (fees) associated with each flash-borrowed asset.\\n * @param initiator The address that initiated the flash loan.\\n * @param onBehalf The address of the user whose debt position will be used for any unpaid flash loan balance.\\n * @param param Additional parameters encoded as bytes. These can be used to pass custom data to the receiver contract.\\n * @return success True if the operation succeeds (regardless of repayment amount), false if the operation fails.\\n * @return repayAmounts Array of uint256 representing the amounts to be repaid for each asset. The receiver contract\\n * must approve these amounts to the respective vToken contracts before this function returns.\\n */\\n function executeOperation(\\n VToken[] calldata vTokens,\\n uint256[] calldata amounts,\\n uint256[] calldata premiums,\\n address initiator,\\n address onBehalf,\\n bytes calldata param\\n ) external returns (bool success, uint256[] memory repayAmounts);\\n}\\n\",\"keccak256\":\"0xe8eb540e98551178726f9d2d24e7ae1ab12ab96349c22f7232bacd377a0b33dd\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ReentrancyGuardTransient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)\\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol\\npragma solidity ^0.8.25;\\n\\nimport { TransientSlot } from \\\"./TransientSlot.sol\\\";\\n\\n/**\\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\\n *\\n * NOTE: This variant only works on networks where EIP-1153 is available.\\n *\\n * _Available since v5.1._\\n */\\nabstract contract ReentrancyGuardTransient {\\n using TransientSlot for *;\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.ReentrancyGuard\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\\n\\n /**\\n * @dev Unauthorized reentrant call.\\n */\\n error ReentrancyGuardReentrantCall();\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return REENTRANCY_GUARD_STORAGE.asBoolean().tload();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be NOT_ENTERED\\n if (_reentrancyGuardEntered()) {\\n revert ReentrancyGuardReentrantCall();\\n }\\n\\n // Any calls to nonReentrant after this point will fail\\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\\n }\\n\\n function _nonReentrantAfter() private {\\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\\n }\\n}\\n\",\"keccak256\":\"0xa27ad29257eb609e5d9ab43d3c84e68c7d22e0ea9bd9dbdc012250e7366d9604\",\"license\":\"MIT\"},\"contracts/Utils/TransientSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/TransientSlot.sol\\npragma solidity ^0.8.25;\\n\\n/**\\n * @dev Library for reading and writing value-types to specific transient storage slots.\\n *\\n * Transient slots are often used to store temporary values that are removed after the current transaction.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * * Example reading and writing values using transient storage:\\n * ```solidity\\n * contract Lock {\\n * using TransientSlot for *;\\n *\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\\n *\\n * modifier locked() {\\n * require(!_LOCK_SLOT.asBoolean().tload());\\n *\\n * _LOCK_SLOT.asBoolean().tstore(true);\\n * _;\\n * _LOCK_SLOT.asBoolean().tstore(false);\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\n */\\nlibrary TransientSlot {\\n /**\\n * @dev UDVT that represent a slot holding a address.\\n */\\n type AddressSlot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a AddressSlot.\\n */\\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\\n return AddressSlot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a bool.\\n */\\n type BooleanSlot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a BooleanSlot.\\n */\\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\\n return BooleanSlot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a bytes32.\\n */\\n type Bytes32Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Bytes32Slot.\\n */\\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\\n return Bytes32Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a uint256.\\n */\\n type Uint256Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Uint256Slot.\\n */\\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\\n return Uint256Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a int256.\\n */\\n type Int256Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Int256Slot.\\n */\\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\\n return Int256Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(AddressSlot slot) internal view returns (address value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(AddressSlot slot, address value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(BooleanSlot slot) internal view returns (bool value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(BooleanSlot slot, bool value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Bytes32Slot slot, bytes32 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Uint256Slot slot, uint256 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Int256Slot slot) internal view returns (int256 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Int256Slot slot, int256 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9ce486f12ba619221439564671d06e5d389b7ac1c72f18d0b08a1e26368a2765\",\"license\":\"MIT\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b50611a838061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106102ff575f3560e01c80639254f5e511610195578063c7ee005e116100e4578063e0f6123d1161009e578063e875544611610079578063e8755446146107ee578063f445d703146107f7578063f851a44014610824578063fa6331d814610836575f80fd5b8063e0f6123d14610782578063e37d4b79146107a4578063e85a2960146107db575f80fd5b8063c7ee005e14610717578063d3270f991461072a578063d463654c1461073d578063d7c46d2d14610744578063dce154491461075c578063dcfbc0c71461076f575f80fd5b8063b8324c7c1161014f578063bec04f721161012a578063bec04f72146106bc578063bf32442d146106c5578063c5b4db55146106d6578063c5f956af14610704575f80fd5b8063b8324c7c1461062f578063bb82aa5e1461068a578063bbb8864a1461069d575f80fd5b80639254f5e5146105b857806394b2294b146105cb57806396c99064146105d45780639bb27d62146105f6578063a657e57914610609578063b2eafc391461061c575f80fd5b80634d99c77611610251578063737690991161020b5780637dc0d1d0116101e65780637dc0d1d0146105575780637fb8e8cd1461056a5780638a7dc165146105775780638c1ac18a14610596575f80fd5b806373769099146104f257806376551383146105325780637d172bd514610544575f80fd5b80634d99c77614610487578063517aa0c71461049a57806352d84d1e146104a25780635544ed9c146104b55780635dd3fc9d146104ca578063719f701b146104e9575f80fd5b806324a3d622116102bc5780634088c73e116102975780634088c73e1461041e57806341a18d2c1461042b578063425fad58146104555780634a58443214610468575f80fd5b806324a3d622146103d957806326782247146103ec5780632bc7e29e146103ff575f80fd5b806302c3bcbb1461030357806304ef9d581461033557806308e0225c1461033e5780630db4b4e51461036857806310b983381461037157806321af4569146103ae575b5f80fd5b6103226103113660046113d6565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61032260225481565b61032261034c3660046113f8565b601360209081525f928352604080842090915290825290205481565b610322601d5481565b61039e61037f3660046113f8565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161032c565b601e546103c1906001600160a01b031681565b6040516001600160a01b03909116815260200161032c565b600a546103c1906001600160a01b031681565b6001546103c1906001600160a01b031681565b61032261040d3660046113d6565b60166020525f908152604090205481565b60185461039e9060ff1681565b6103226104393660046113f8565b601260209081525f928352604080842090915290825290205481565b60185461039e9062010000900460ff1681565b6103226104763660046113d6565b601f6020525f908152604090205481565b61032261049536600461144a565b61083f565b61032260c881565b6103c16104b0366004611464565b610860565b6104c86104c33660046115bb565b610888565b005b6103226104d83660046113d6565b602b6020525f908152604090205481565b610322601c5481565b61051a6105003660046113d6565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161032c565b60185461039e90610100900460ff1681565b601b546103c1906001600160a01b031681565b6004546103c1906001600160a01b031681565b60395461039e9060ff1681565b6103226105853660046113d6565b60146020525f908152604090205481565b61039e6105a43660046113d6565b602d6020525f908152604090205460ff1681565b6015546103c1906001600160a01b031681565b61032260075481565b6105e76105e23660046116c0565b610b7a565b60405161032c93929190611707565b6025546103c1906001600160a01b031681565b60375461051a906001600160601b031681565b6020546103c1906001600160a01b031681565b61066661063d3660046113d6565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161032c565b6002546103c1906001600160a01b031681565b6103226106ab3660046113d6565b602a6020525f908152604090205481565b61032260175481565b6033546001600160a01b03166103c1565b6106ec6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b03909116815260200161032c565b6021546103c1906001600160a01b031681565b6031546103c1906001600160a01b031681565b6026546103c1906001600160a01b031681565b61051a5f81565b6039546103c19061010090046001600160a01b031681565b6103c161076a366004611730565b610c27565b6003546103c1906001600160a01b031681565b61039e6107903660046113d6565b60386020525f908152604090205460ff1681565b6106666107b23660046113d6565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61039e6107e936600461175a565b610c5b565b61032260055481565b61039e6108053660046113f8565b603260209081525f928352604080842090915290825290205460ff1681565b5f546103c1906001600160a01b031681565b610322601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d818154811061086f575f80fd5b5f918252602090912001546001600160a01b0316905081565b610890610c9f565b60395460ff16156108b4576040516323118a8360e01b815260040160405180910390fd5b6108bd85610d0e565b82515f8181036108e05760405163bd96af5b60e01b815260040160405180910390fd5b60c88211156109115760405163d2f1924360e01b81526004810183905260c860248201526044015b60405180910390fd5b835182146109325760405163aa6eb14560e01b815260040160405180910390fd5b5f5b82811015610a845761095e86828151811061095157610951611789565b6020026020010151610d5f565b805490925060ff166109ad5785818151811061097c5761097c611789565b6020026020010151604051635a9a1eb960e11b815260040161090891906001600160a01b0391909116815260200190565b8581815181106109bf576109bf611789565b60200260200101516001600160a01b031663ae3fcb1f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a02573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a2691906117ac565b610a4357604051630a3fad8360e01b815260040160405180910390fd5b848181518110610a5557610a55611789565b60200260200101515f03610a7c5760405163162908e360e11b815260040160405180910390fd5b600101610934565b50610a8e86610d0e565b335f9081526038602052604090205460ff16610abf576040516319d14ecf60e01b8152336004820152602401610908565b336001600160a01b03881614801590610afb57506001600160a01b0387165f908152602c6020908152604080832033845290915290205460ff16155b15610b19576040516337248ad960e01b815260040160405180910390fd5b610b268787878787610d81565b856001600160a01b03167f785e5057f6e5f2e298f8dce2755a6ef29f9dd8a0f82a8b5cad101ea5ef803f048686604051610b61929190611837565b60405180910390a25050610b73610e5c565b5050505050565b60366020525f9081526040902080548190610b9490611864565b80601f0160208091040260200160405190810160405280929190818152602001828054610bc090611864565b8015610c0b5780601f10610be257610100808354040283529160200191610c0b565b820191905f5260205f20905b815481529060010190602001808311610bee57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6008602052815f5260405f208181548110610c40575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610c8557610c8561189c565b815260208101919091526040015f205460ff169392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15610cdf57604051633ee5aeb560e01b815260040160405180910390fd5b610d0c60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90610e86565b565b6001600160a01b038116610d5c5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610908565b50565b5f60095f610d6d5f8561083f565b81526020019081526020015f209050919050565b604080518082019091526060808252602082015283518067ffffffffffffffff811115610db057610db061147b565b604051908082528060200260200182016040528015610dd9578160200160208202803683370190505b5082528067ffffffffffffffff811115610df557610df561147b565b604051908082528060200260200182016040528015610e1e578160200160208202803683370190505b506020830152610e3086868685610e8d565b5f610e4288888888875f01518961102d565b9050610e528888888885886110d7565b5050505050505050565b610d0c5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00610d06565b80825d5050565b82515f5b8181101561102557848181518110610eab57610eab611789565b60200260200101516001600160a01b03166371507cd5858381518110610ed357610ed3611789565b60200260200101516040518263ffffffff1660e01b8152600401610ef991815260200190565b6040805180830381865afa158015610f13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3791906118b0565b8451805184908110610f4b57610f4b611789565b6020026020010185602001518481518110610f6857610f68611789565b6020026020010182815250828152505050848181518110610f8b57610f8b611789565b60200260200101516001600160a01b0316638d1f23d487868481518110610fb457610fb4611789565b60200260200101516040518363ffffffff1660e01b8152600401610fed9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b158015611004575f80fd5b505af1158015611016573d5f803e3d5ffd5b50505050806001019050610e91565b505050505050565b60605f80876001600160a01b031663fc08f9f6888888338e8a6040518763ffffffff1660e01b8152600401611067969594939291906118d2565b5f604051808303815f875af1158015611082573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110a99190810190611942565b91509150816110cb57604051635a3b2cbb60e11b815260040160405180910390fd5b98975050505050505050565b83515f5b81811015610e52576111768682815181106110f8576110f8611789565b6020026020010151898988858151811061111457611114611789565b602002602001015188868151811061112e5761112e611789565b6020026020010151885f0151878151811061114b5761114b611789565b60200260200101518960200151888151811061116957611169611789565b602002602001015161117e565b6001016110db565b5f61118983866119f5565b90505f818511611199578461119b565b815b9050838110156111c85760405163bcb60bf360e01b81526004810182905260248101859052604401610908565b60405163324235c960e11b81526001600160a01b0388811660048301526024820183905260448201869052606482018590525f91908b16906364846b92906084016020604051808303815f875af1158015611225573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112499190611a08565b90505f818411156112f65761125e8285611a1f565b6040516366ce8d7d60e01b81526001600160a01b038c81166004830152602482018390529192505f918d16906366ce8d7d906044016020604051808303815f875af11580156112af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d39190611a08565b905080156112f45760405163ab52b56f60e01b815260040160405180910390fd5b505b8a6001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611332573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113569190611a32565b6001600160a01b03168a6001600160a01b03168a6001600160a01b03167f499433c603d8d6db664daa76d7158679cc9f90c4c30723e29495a8c39302a17385856040516113ad929190918252602082015260400190565b60405180910390a45050505050505050505050565b6001600160a01b0381168114610d5c575f80fd5b5f602082840312156113e6575f80fd5b81356113f1816113c2565b9392505050565b5f8060408385031215611409575f80fd5b8235611414816113c2565b91506020830135611424816113c2565b809150509250929050565b80356001600160601b0381168114611445575f80fd5b919050565b5f806040838503121561145b575f80fd5b6114148361142f565b5f60208284031215611474575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114b8576114b861147b565b604052919050565b5f67ffffffffffffffff8211156114d9576114d961147b565b5060051b60200190565b5f82601f8301126114f2575f80fd5b81356020611507611502836114c0565b61148f565b8083825260208201915060208460051b870101935086841115611528575f80fd5b602086015b84811015611544578035835291830191830161152d565b509695505050505050565b5f82601f83011261155e575f80fd5b813567ffffffffffffffff8111156115785761157861147b565b61158b601f8201601f191660200161148f565b81815284602083860101111561159f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a086880312156115cf575f80fd5b85356115da816113c2565b94506020868101356115eb816113c2565b9450604087013567ffffffffffffffff80821115611607575f80fd5b818901915089601f83011261161a575f80fd5b8135611628611502826114c0565b81815260059190911b8301840190848101908c831115611646575f80fd5b938501935b8285101561166d57843561165e816113c2565b8252938501939085019061164b565b975050506060890135925080831115611684575f80fd5b6116908a848b016114e3565b945060808901359250808311156116a5575f80fd5b50506116b38882890161154f565b9150509295509295909350565b5f602082840312156116d0575f80fd5b6113f18261142f565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61171960608301866116d9565b931515602083015250901515604090910152919050565b5f8060408385031215611741575f80fd5b823561174c816113c2565b946020939093013593505050565b5f806040838503121561176b575f80fd5b8235611776816113c2565b9150602083013560098110611424575f80fd5b634e487b7160e01b5f52603260045260245ffd5b80518015158114611445575f80fd5b5f602082840312156117bc575f80fd5b6113f18261179d565b5f815180845260208085019450602084015f5b838110156117fd5781516001600160a01b0316875295820195908201906001016117d8565b509495945050505050565b5f815180845260208085019450602084015f5b838110156117fd5781518752958201959082019060010161181b565b604081525f61184960408301856117c5565b828103602084015261185b8185611808565b95945050505050565b600181811c9082168061187857607f821691505b60208210810361189657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156118c1575f80fd5b505080516020909101519092909150565b60c081525f6118e460c08301896117c5565b82810360208401526118f68189611808565b9050828103604084015261190a8188611808565b6001600160a01b0387811660608601528616608085015283810360a0850152905061193581856116d9565b9998505050505050505050565b5f8060408385031215611953575f80fd5b61195c8361179d565b915060208084015167ffffffffffffffff811115611978575f80fd5b8401601f81018613611988575f80fd5b8051611996611502826114c0565b81815260059190911b820183019083810190888311156119b4575f80fd5b928401925b828410156119d2578351825292840192908401906119b9565b80955050505050509250929050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561085a5761085a6119e1565b5f60208284031215611a18575f80fd5b5051919050565b8181038181111561085a5761085a6119e1565b5f60208284031215611a42575f80fd5b81516113f1816113c256fea264697066735822122057130d8d3b1b9b68d3c2725c0f7881b180994c9562d451c8bf767d91e685f46e64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102ff575f3560e01c80639254f5e511610195578063c7ee005e116100e4578063e0f6123d1161009e578063e875544611610079578063e8755446146107ee578063f445d703146107f7578063f851a44014610824578063fa6331d814610836575f80fd5b8063e0f6123d14610782578063e37d4b79146107a4578063e85a2960146107db575f80fd5b8063c7ee005e14610717578063d3270f991461072a578063d463654c1461073d578063d7c46d2d14610744578063dce154491461075c578063dcfbc0c71461076f575f80fd5b8063b8324c7c1161014f578063bec04f721161012a578063bec04f72146106bc578063bf32442d146106c5578063c5b4db55146106d6578063c5f956af14610704575f80fd5b8063b8324c7c1461062f578063bb82aa5e1461068a578063bbb8864a1461069d575f80fd5b80639254f5e5146105b857806394b2294b146105cb57806396c99064146105d45780639bb27d62146105f6578063a657e57914610609578063b2eafc391461061c575f80fd5b80634d99c77611610251578063737690991161020b5780637dc0d1d0116101e65780637dc0d1d0146105575780637fb8e8cd1461056a5780638a7dc165146105775780638c1ac18a14610596575f80fd5b806373769099146104f257806376551383146105325780637d172bd514610544575f80fd5b80634d99c77614610487578063517aa0c71461049a57806352d84d1e146104a25780635544ed9c146104b55780635dd3fc9d146104ca578063719f701b146104e9575f80fd5b806324a3d622116102bc5780634088c73e116102975780634088c73e1461041e57806341a18d2c1461042b578063425fad58146104555780634a58443214610468575f80fd5b806324a3d622146103d957806326782247146103ec5780632bc7e29e146103ff575f80fd5b806302c3bcbb1461030357806304ef9d581461033557806308e0225c1461033e5780630db4b4e51461036857806310b983381461037157806321af4569146103ae575b5f80fd5b6103226103113660046113d6565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61032260225481565b61032261034c3660046113f8565b601360209081525f928352604080842090915290825290205481565b610322601d5481565b61039e61037f3660046113f8565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161032c565b601e546103c1906001600160a01b031681565b6040516001600160a01b03909116815260200161032c565b600a546103c1906001600160a01b031681565b6001546103c1906001600160a01b031681565b61032261040d3660046113d6565b60166020525f908152604090205481565b60185461039e9060ff1681565b6103226104393660046113f8565b601260209081525f928352604080842090915290825290205481565b60185461039e9062010000900460ff1681565b6103226104763660046113d6565b601f6020525f908152604090205481565b61032261049536600461144a565b61083f565b61032260c881565b6103c16104b0366004611464565b610860565b6104c86104c33660046115bb565b610888565b005b6103226104d83660046113d6565b602b6020525f908152604090205481565b610322601c5481565b61051a6105003660046113d6565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161032c565b60185461039e90610100900460ff1681565b601b546103c1906001600160a01b031681565b6004546103c1906001600160a01b031681565b60395461039e9060ff1681565b6103226105853660046113d6565b60146020525f908152604090205481565b61039e6105a43660046113d6565b602d6020525f908152604090205460ff1681565b6015546103c1906001600160a01b031681565b61032260075481565b6105e76105e23660046116c0565b610b7a565b60405161032c93929190611707565b6025546103c1906001600160a01b031681565b60375461051a906001600160601b031681565b6020546103c1906001600160a01b031681565b61066661063d3660046113d6565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161032c565b6002546103c1906001600160a01b031681565b6103226106ab3660046113d6565b602a6020525f908152604090205481565b61032260175481565b6033546001600160a01b03166103c1565b6106ec6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b03909116815260200161032c565b6021546103c1906001600160a01b031681565b6031546103c1906001600160a01b031681565b6026546103c1906001600160a01b031681565b61051a5f81565b6039546103c19061010090046001600160a01b031681565b6103c161076a366004611730565b610c27565b6003546103c1906001600160a01b031681565b61039e6107903660046113d6565b60386020525f908152604090205460ff1681565b6106666107b23660046113d6565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61039e6107e936600461175a565b610c5b565b61032260055481565b61039e6108053660046113f8565b603260209081525f928352604080842090915290825290205460ff1681565b5f546103c1906001600160a01b031681565b610322601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d818154811061086f575f80fd5b5f918252602090912001546001600160a01b0316905081565b610890610c9f565b60395460ff16156108b4576040516323118a8360e01b815260040160405180910390fd5b6108bd85610d0e565b82515f8181036108e05760405163bd96af5b60e01b815260040160405180910390fd5b60c88211156109115760405163d2f1924360e01b81526004810183905260c860248201526044015b60405180910390fd5b835182146109325760405163aa6eb14560e01b815260040160405180910390fd5b5f5b82811015610a845761095e86828151811061095157610951611789565b6020026020010151610d5f565b805490925060ff166109ad5785818151811061097c5761097c611789565b6020026020010151604051635a9a1eb960e11b815260040161090891906001600160a01b0391909116815260200190565b8581815181106109bf576109bf611789565b60200260200101516001600160a01b031663ae3fcb1f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a02573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a2691906117ac565b610a4357604051630a3fad8360e01b815260040160405180910390fd5b848181518110610a5557610a55611789565b60200260200101515f03610a7c5760405163162908e360e11b815260040160405180910390fd5b600101610934565b50610a8e86610d0e565b335f9081526038602052604090205460ff16610abf576040516319d14ecf60e01b8152336004820152602401610908565b336001600160a01b03881614801590610afb57506001600160a01b0387165f908152602c6020908152604080832033845290915290205460ff16155b15610b19576040516337248ad960e01b815260040160405180910390fd5b610b268787878787610d81565b856001600160a01b03167f785e5057f6e5f2e298f8dce2755a6ef29f9dd8a0f82a8b5cad101ea5ef803f048686604051610b61929190611837565b60405180910390a25050610b73610e5c565b5050505050565b60366020525f9081526040902080548190610b9490611864565b80601f0160208091040260200160405190810160405280929190818152602001828054610bc090611864565b8015610c0b5780601f10610be257610100808354040283529160200191610c0b565b820191905f5260205f20905b815481529060010190602001808311610bee57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6008602052815f5260405f208181548110610c40575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610c8557610c8561189c565b815260208101919091526040015f205460ff169392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15610cdf57604051633ee5aeb560e01b815260040160405180910390fd5b610d0c60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90610e86565b565b6001600160a01b038116610d5c5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610908565b50565b5f60095f610d6d5f8561083f565b81526020019081526020015f209050919050565b604080518082019091526060808252602082015283518067ffffffffffffffff811115610db057610db061147b565b604051908082528060200260200182016040528015610dd9578160200160208202803683370190505b5082528067ffffffffffffffff811115610df557610df561147b565b604051908082528060200260200182016040528015610e1e578160200160208202803683370190505b506020830152610e3086868685610e8d565b5f610e4288888888875f01518961102d565b9050610e528888888885886110d7565b5050505050505050565b610d0c5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00610d06565b80825d5050565b82515f5b8181101561102557848181518110610eab57610eab611789565b60200260200101516001600160a01b03166371507cd5858381518110610ed357610ed3611789565b60200260200101516040518263ffffffff1660e01b8152600401610ef991815260200190565b6040805180830381865afa158015610f13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3791906118b0565b8451805184908110610f4b57610f4b611789565b6020026020010185602001518481518110610f6857610f68611789565b6020026020010182815250828152505050848181518110610f8b57610f8b611789565b60200260200101516001600160a01b0316638d1f23d487868481518110610fb457610fb4611789565b60200260200101516040518363ffffffff1660e01b8152600401610fed9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b158015611004575f80fd5b505af1158015611016573d5f803e3d5ffd5b50505050806001019050610e91565b505050505050565b60605f80876001600160a01b031663fc08f9f6888888338e8a6040518763ffffffff1660e01b8152600401611067969594939291906118d2565b5f604051808303815f875af1158015611082573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110a99190810190611942565b91509150816110cb57604051635a3b2cbb60e11b815260040160405180910390fd5b98975050505050505050565b83515f5b81811015610e52576111768682815181106110f8576110f8611789565b6020026020010151898988858151811061111457611114611789565b602002602001015188868151811061112e5761112e611789565b6020026020010151885f0151878151811061114b5761114b611789565b60200260200101518960200151888151811061116957611169611789565b602002602001015161117e565b6001016110db565b5f61118983866119f5565b90505f818511611199578461119b565b815b9050838110156111c85760405163bcb60bf360e01b81526004810182905260248101859052604401610908565b60405163324235c960e11b81526001600160a01b0388811660048301526024820183905260448201869052606482018590525f91908b16906364846b92906084016020604051808303815f875af1158015611225573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112499190611a08565b90505f818411156112f65761125e8285611a1f565b6040516366ce8d7d60e01b81526001600160a01b038c81166004830152602482018390529192505f918d16906366ce8d7d906044016020604051808303815f875af11580156112af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d39190611a08565b905080156112f45760405163ab52b56f60e01b815260040160405180910390fd5b505b8a6001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611332573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113569190611a32565b6001600160a01b03168a6001600160a01b03168a6001600160a01b03167f499433c603d8d6db664daa76d7158679cc9f90c4c30723e29495a8c39302a17385856040516113ad929190918252602082015260400190565b60405180910390a45050505050505050505050565b6001600160a01b0381168114610d5c575f80fd5b5f602082840312156113e6575f80fd5b81356113f1816113c2565b9392505050565b5f8060408385031215611409575f80fd5b8235611414816113c2565b91506020830135611424816113c2565b809150509250929050565b80356001600160601b0381168114611445575f80fd5b919050565b5f806040838503121561145b575f80fd5b6114148361142f565b5f60208284031215611474575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114b8576114b861147b565b604052919050565b5f67ffffffffffffffff8211156114d9576114d961147b565b5060051b60200190565b5f82601f8301126114f2575f80fd5b81356020611507611502836114c0565b61148f565b8083825260208201915060208460051b870101935086841115611528575f80fd5b602086015b84811015611544578035835291830191830161152d565b509695505050505050565b5f82601f83011261155e575f80fd5b813567ffffffffffffffff8111156115785761157861147b565b61158b601f8201601f191660200161148f565b81815284602083860101111561159f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a086880312156115cf575f80fd5b85356115da816113c2565b94506020868101356115eb816113c2565b9450604087013567ffffffffffffffff80821115611607575f80fd5b818901915089601f83011261161a575f80fd5b8135611628611502826114c0565b81815260059190911b8301840190848101908c831115611646575f80fd5b938501935b8285101561166d57843561165e816113c2565b8252938501939085019061164b565b975050506060890135925080831115611684575f80fd5b6116908a848b016114e3565b945060808901359250808311156116a5575f80fd5b50506116b38882890161154f565b9150509295509295909350565b5f602082840312156116d0575f80fd5b6113f18261142f565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61171960608301866116d9565b931515602083015250901515604090910152919050565b5f8060408385031215611741575f80fd5b823561174c816113c2565b946020939093013593505050565b5f806040838503121561176b575f80fd5b8235611776816113c2565b9150602083013560098110611424575f80fd5b634e487b7160e01b5f52603260045260245ffd5b80518015158114611445575f80fd5b5f602082840312156117bc575f80fd5b6113f18261179d565b5f815180845260208085019450602084015f5b838110156117fd5781516001600160a01b0316875295820195908201906001016117d8565b509495945050505050565b5f815180845260208085019450602084015f5b838110156117fd5781518752958201959082019060010161181b565b604081525f61184960408301856117c5565b828103602084015261185b8185611808565b95945050505050565b600181811c9082168061187857607f821691505b60208210810361189657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156118c1575f80fd5b505080516020909101519092909150565b60c081525f6118e460c08301896117c5565b82810360208401526118f68189611808565b9050828103604084015261190a8188611808565b6001600160a01b0387811660608601528616608085015283810360a0850152905061193581856116d9565b9998505050505050505050565b5f8060408385031215611953575f80fd5b61195c8361179d565b915060208084015167ffffffffffffffff811115611978575f80fd5b8401601f81018613611988575f80fd5b8051611996611502826114c0565b81815260059190911b820183019083810190888311156119b4575f80fd5b928401925b828410156119d2578351825292840192908401906119b9565b80955050505050509250929050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561085a5761085a6119e1565b5f60208284031215611a18575f80fd5b5051919050565b8181038181111561085a5761085a6119e1565b5f60208284031215611a42575f80fd5b81516113f1816113c256fea264697066735822122057130d8d3b1b9b68d3c2725c0f7881b180994c9562d451c8bf767d91e685f46e64736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This contract implements flash loan functionality allowing users to borrow assets temporarily within a single transaction. Users can borrow multiple assets simultaneously and have the flexibility to repay partially, with unpaid balances automatically converted to debt positions. The contract supports protocol fee collection and integrates with the Venus lending protocol.", @@ -1417,6 +1430,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "executeFlashLoan(address,address,address[],uint256[],bytes)": { "notice": "Executes a flashLoan operation with the requested assets." }, @@ -1523,7 +1539,7 @@ "storageLayout": { "storage": [ { - "astId": 1652, + "astId": 9226, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "admin", "offset": 0, @@ -1531,7 +1547,7 @@ "type": "t_address" }, { - "astId": 1655, + "astId": 9229, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "pendingAdmin", "offset": 0, @@ -1539,7 +1555,7 @@ "type": "t_address" }, { - "astId": 1658, + "astId": 9232, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "comptrollerImplementation", "offset": 0, @@ -1547,7 +1563,7 @@ "type": "t_address" }, { - "astId": 1661, + "astId": 9235, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -1555,15 +1571,15 @@ "type": "t_address" }, { - "astId": 1668, + "astId": 9242, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)967" + "type": "t_contract(ResilientOracleInterface)7913" }, { - "astId": 1671, + "astId": 9245, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "closeFactorMantissa", "offset": 0, @@ -1571,7 +1587,7 @@ "type": "t_uint256" }, { - "astId": 1674, + "astId": 9248, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -1579,7 +1595,7 @@ "type": "t_uint256" }, { - "astId": 1677, + "astId": 9251, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "maxAssets", "offset": 0, @@ -1587,23 +1603,23 @@ "type": "t_uint256" }, { - "astId": 1684, + "astId": 9258, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)17915)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)" }, { - "astId": 1718, + "astId": 9292, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11388,t_struct(Market)1711_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)" }, { - "astId": 1721, + "astId": 9295, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "pauseGuardian", "offset": 0, @@ -1611,7 +1627,7 @@ "type": "t_address" }, { - "astId": 1724, + "astId": 9298, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -1619,7 +1635,7 @@ "type": "t_bool" }, { - "astId": 1727, + "astId": 9301, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -1627,7 +1643,7 @@ "type": "t_bool" }, { - "astId": 1730, + "astId": 9304, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "transferGuardianPaused", "offset": 22, @@ -1635,7 +1651,7 @@ "type": "t_bool" }, { - "astId": 1733, + "astId": 9307, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -1643,7 +1659,7 @@ "type": "t_bool" }, { - "astId": 1738, + "astId": 9312, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "mintGuardianPaused", "offset": 0, @@ -1651,7 +1667,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1743, + "astId": 9317, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -1659,15 +1675,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1755, + "astId": 9329, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)17915)dyn_storage" + "type": "t_array(t_contract(VToken)49461)dyn_storage" }, { - "astId": 1758, + "astId": 9332, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusRate", "offset": 0, @@ -1675,7 +1691,7 @@ "type": "t_uint256" }, { - "astId": 1763, + "astId": 9337, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusSpeeds", "offset": 0, @@ -1683,23 +1699,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1769, + "astId": 9343, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1775, + "astId": 9349, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1782, + "astId": 9356, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusSupplierIndex", "offset": 0, @@ -1707,7 +1723,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1789, + "astId": 9363, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -1715,7 +1731,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1794, + "astId": 9368, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusAccrued", "offset": 0, @@ -1723,15 +1739,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1798, + "astId": 9372, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)11813" + "type": "t_contract(VAIControllerInterface)42511" }, { - "astId": 1803, + "astId": 9377, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "mintedVAIs", "offset": 0, @@ -1739,7 +1755,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1806, + "astId": 9380, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "vaiMintRate", "offset": 0, @@ -1747,7 +1763,7 @@ "type": "t_uint256" }, { - "astId": 1809, + "astId": 9383, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -1755,7 +1771,7 @@ "type": "t_bool" }, { - "astId": 1811, + "astId": 9385, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -1763,7 +1779,7 @@ "type": "t_bool" }, { - "astId": 1814, + "astId": 9388, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "protocolPaused", "offset": 2, @@ -1771,7 +1787,7 @@ "type": "t_bool" }, { - "astId": 1817, + "astId": 9391, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusVAIRate", "offset": 0, @@ -1779,7 +1795,7 @@ "type": "t_uint256" }, { - "astId": 1823, + "astId": 9397, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -1787,7 +1803,7 @@ "type": "t_uint256" }, { - "astId": 1825, + "astId": 9399, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "vaiVaultAddress", "offset": 0, @@ -1795,7 +1811,7 @@ "type": "t_address" }, { - "astId": 1827, + "astId": 9401, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "releaseStartBlock", "offset": 0, @@ -1803,7 +1819,7 @@ "type": "t_uint256" }, { - "astId": 1829, + "astId": 9403, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "minReleaseAmount", "offset": 0, @@ -1811,7 +1827,7 @@ "type": "t_uint256" }, { - "astId": 1835, + "astId": 9409, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "borrowCapGuardian", "offset": 0, @@ -1819,7 +1835,7 @@ "type": "t_address" }, { - "astId": 1840, + "astId": 9414, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "borrowCaps", "offset": 0, @@ -1827,7 +1843,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1846, + "astId": 9420, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "treasuryGuardian", "offset": 0, @@ -1835,7 +1851,7 @@ "type": "t_address" }, { - "astId": 1849, + "astId": 9423, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "treasuryAddress", "offset": 0, @@ -1843,7 +1859,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9426, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "treasuryPercent", "offset": 0, @@ -1851,7 +1867,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9434, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -1859,7 +1875,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1865, + "astId": 9439, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "lastContributorBlock", "offset": 0, @@ -1867,7 +1883,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1870, + "astId": 9444, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "liquidatorContract", "offset": 0, @@ -1875,15 +1891,15 @@ "type": "t_address" }, { - "astId": 1876, + "astId": 9450, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1635" + "type": "t_contract(ComptrollerLensInterface)9207" }, { - "astId": 1884, + "astId": 9458, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "supplyCaps", "offset": 0, @@ -1891,7 +1907,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9464, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "accessControl", "offset": 0, @@ -1899,7 +1915,7 @@ "type": "t_address" }, { - "astId": 1897, + "astId": 9471, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_actionPaused", "offset": 0, @@ -1907,7 +1923,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1905, + "astId": 9479, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -1915,7 +1931,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1910, + "astId": 9484, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -1923,7 +1939,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1920, + "astId": 9494, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "approvedDelegates", "offset": 0, @@ -1931,7 +1947,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1928, + "astId": 9502, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -1939,23 +1955,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1947, + "astId": 9521, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1936_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)" }, { - "astId": 1952, + "astId": 9526, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1942_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)" }, { - "astId": 1955, + "astId": 9529, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_facetAddresses", "offset": 0, @@ -1963,15 +1979,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1962, + "astId": 9536, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)11746" + "type": "t_contract(IPrime)33730" }, { - "astId": 1972, + "astId": 9546, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -1979,7 +1995,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1978, + "astId": 9552, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "xvs", "offset": 0, @@ -1987,7 +2003,7 @@ "type": "t_address" }, { - "astId": 1981, + "astId": 9555, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "xvsVToken", "offset": 0, @@ -1995,7 +2011,7 @@ "type": "t_address" }, { - "astId": 2003, + "astId": 9577, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "userPoolId", "offset": 0, @@ -2003,15 +2019,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2009, + "astId": 9583, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)1998_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)9572_storage)" }, { - "astId": 2012, + "astId": 9586, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "lastPoolId", "offset": 0, @@ -2019,7 +2035,7 @@ "type": "t_uint96" }, { - "astId": 2020, + "astId": 9594, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -2027,12 +2043,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2023, + "astId": 9597, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 9604, + "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)7883" } ], "types": { @@ -2053,8 +2077,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)17915)dyn_storage": { - "base": "t_contract(VToken)17915", + "t_array(t_contract(VToken)49461)dyn_storage": { + "base": "t_contract(VToken)49461", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -2069,37 +2093,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1635": { + "t_contract(ComptrollerLensInterface)9207": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)11746": { + "t_contract(IDeviationBoundedOracle)7883": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)33730": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)967": { + "t_contract(ResilientOracleInterface)7913": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)11813": { + "t_contract(VAIControllerInterface)42511": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)17915": { + "t_contract(VToken)49461": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)17915)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)17915)dyn_storage" + "value": "t_array(t_contract(VToken)49461)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -2129,19 +2158,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1942_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1942_storage" + "value": "t_struct(FacetFunctionSelectors)9516_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1750_storage" + "value": "t_struct(VenusMarketState)9324_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2157,12 +2186,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1936_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1936_storage" + "value": "t_struct(FacetAddressAndPosition)9510_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -2171,31 +2200,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)1998_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)9572_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)1998_storage" + "value": "t_struct(PoolData)9572_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11388,t_struct(Market)1711_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11388", + "key": "t_userDefinedValueType(PoolMarketId)19217", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1711_storage" + "value": "t_struct(Market)9285_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1936_storage": { + "t_struct(FacetAddressAndPosition)9510_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1933, + "astId": 9507, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "facetAddress", "offset": 0, @@ -2203,7 +2232,7 @@ "type": "t_address" }, { - "astId": 1935, + "astId": 9509, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "functionSelectorPosition", "offset": 20, @@ -2213,12 +2242,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1942_storage": { + "t_struct(FacetFunctionSelectors)9516_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1939, + "astId": 9513, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "functionSelectors", "offset": 0, @@ -2226,7 +2255,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1941, + "astId": 9515, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "facetAddressPosition", "offset": 0, @@ -2236,12 +2265,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1711_storage": { + "t_struct(Market)9285_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1687, + "astId": 9261, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isListed", "offset": 0, @@ -2249,7 +2278,7 @@ "type": "t_bool" }, { - "astId": 1690, + "astId": 9264, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -2257,7 +2286,7 @@ "type": "t_uint256" }, { - "astId": 1695, + "astId": 9269, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "accountMembership", "offset": 0, @@ -2265,7 +2294,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1698, + "astId": 9272, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isVenus", "offset": 0, @@ -2273,7 +2302,7 @@ "type": "t_bool" }, { - "astId": 1701, + "astId": 9275, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -2281,7 +2310,7 @@ "type": "t_uint256" }, { - "astId": 1704, + "astId": 9278, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -2289,7 +2318,7 @@ "type": "t_uint256" }, { - "astId": 1707, + "astId": 9281, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "poolId", "offset": 0, @@ -2297,7 +2326,7 @@ "type": "t_uint96" }, { - "astId": 1710, + "astId": 9284, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isBorrowAllowed", "offset": 12, @@ -2307,12 +2336,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)1998_storage": { + "t_struct(PoolData)9572_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 1987, + "astId": 9561, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "label", "offset": 0, @@ -2320,7 +2349,7 @@ "type": "t_string_storage" }, { - "astId": 1991, + "astId": 9565, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "vTokens", "offset": 0, @@ -2328,7 +2357,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1994, + "astId": 9568, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isActive", "offset": 0, @@ -2336,7 +2365,7 @@ "type": "t_bool" }, { - "astId": 1997, + "astId": 9571, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -2346,12 +2375,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1750_storage": { + "t_struct(VenusMarketState)9324_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1746, + "astId": 9320, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "index", "offset": 0, @@ -2359,7 +2388,7 @@ "type": "t_uint224" }, { - "astId": 1749, + "astId": 9323, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "block", "offset": 28, @@ -2389,7 +2418,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11388": { + "t_userDefinedValueType(PoolMarketId)19217": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bscmainnet/MarketFacet.json b/deployments/bscmainnet/MarketFacet.json index 4841c89be..98affff75 100644 --- a/deployments/bscmainnet/MarketFacet.json +++ b/deployments/bscmainnet/MarketFacet.json @@ -1,5 +1,5 @@ { - "address": "0x87FdF72FA2fB29Cb43f03aCa261A8DC2C613a860", + "address": "0x7397B6bcFA9332Cc8791c886F339B4D114651719", "abi": [ { "inputs": [], @@ -712,6 +712,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1889,28 +1902,28 @@ "type": "function" } ], - "transactionHash": "0x7277acbfdb15354f351fbe9cba46526bc67e2638fa06555de9c1f556cfacb234", + "transactionHash": "0x84641fe854f279d406f6c2df83e2982bd8bf74f4f9858dd0608fd670eecede7a", "receipt": { "to": null, - "from": "0x14A1c22EF6d2eF6cE33c0b018d8A34D02021e5c8", - "contractAddress": "0x87FdF72FA2fB29Cb43f03aCa261A8DC2C613a860", - "transactionIndex": 105, - "gasUsed": "3157624", + "from": "0x9b0A3EAE7f174937d31745B710BbeA68e9D1BEf7", + "contractAddress": "0x7397B6bcFA9332Cc8791c886F339B4D114651719", + "transactionIndex": 43, + "gasUsed": "3228522", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb1572bc0a083401a2885cc52603c0d784d58e6cb0ee97370c2e208c9dcffd710", - "transactionHash": "0x7277acbfdb15354f351fbe9cba46526bc67e2638fa06555de9c1f556cfacb234", + "blockHash": "0xb080549e7e886f6d34437cf35f81a2383c75481312b795d9300a5d5c0ebd287b", + "transactionHash": "0x84641fe854f279d406f6c2df83e2982bd8bf74f4f9858dd0608fd670eecede7a", "logs": [], - "blockNumber": 68832406, - "cumulativeGasUsed": "13572437", + "blockNumber": 95559346, + "cumulativeGasUsed": "10066772", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "34e3f00342319d109c5ecd417df3f3a4", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"DelegateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketUnlisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"PoolCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"PoolMarketInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"previousPoolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"newPoolId\",\"type\":\"uint96\"}],\"name\":\"PoolSelected\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96[]\",\"name\":\"poolIds\",\"type\":\"uint96[]\"},{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"addPoolMarkets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"createPool\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"enterMarketBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"enterPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getEffectiveLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"enum WeightFunction\",\"name\":\"weightingStrategy\",\"type\":\"uint8\"}],\"name\":\"getEffectiveLtvFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getLiquidationThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"getPoolVTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"targetPoolId\",\"type\":\"uint96\"}],\"name\":\"hasValidPoolBorrows\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"isMarketListed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateVAICalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isVenus\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"marketPoolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"isBorrowAllowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"poolMarkets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isVenus\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"marketPoolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"isBorrowAllowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"removePoolMarket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"unlistMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"updateDelegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the methods related to the market's management in the pool\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_supportMarket(address)\":{\"details\":\"Allows a privileged role to add and list markets to the Comptroller\",\"params\":{\"vToken\":\"The address of the vToken market to list in the Core Pool\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"addPoolMarkets(uint96[],address[])\":{\"custom:error\":\"ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.MarketNotListedInCorePool Reverts if the market is not listed in the core pool.MarketAlreadyListed Reverts if the given market is already listed in the specified pool.InactivePool Reverts if attempted to add markets to an inactive pool.\",\"custom:event\":\"PoolMarketInitialized Emitted after successfully initializing a market in a pool.\",\"params\":{\"poolIds\":\"Array of pool IDs.\",\"vTokens\":\"Array of market (vToken) addresses.\"}},\"checkMembership(address,address)\":{\"details\":\"Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools, all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\",\"params\":{\"account\":\"The address of the account to check\",\"vToken\":\"The vToken to check\"},\"returns\":{\"_0\":\"True if the account is in the asset, otherwise false\"}},\"createPool(string)\":{\"custom:error\":\"EmptyPoolLabel Reverts if the provided label is an empty string.\",\"custom:event\":\"PoolCreated Emitted after successfully creating a new pool.\",\"params\":{\"label\":\"name for the pool (must be non-empty).\"},\"returns\":{\"_0\":\"poolId The incremental unique identifier of the newly created pool.\"}},\"enterMarketBehalf(address,address)\":{\"custom:error\":\"NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\",\"details\":\"Only callable by the account itself or an approved delegate\",\"params\":{\"onBehalf\":\"The address of the account entering the market\",\"vToken\":\"The address of the vToken market to enable for the account\"},\"returns\":{\"_0\":\"uint256 indicating the result (0 = success, non-zero = failure)\"}},\"enterMarkets(address[])\":{\"params\":{\"vTokens\":\"The list of addresses of the vToken markets to be enabled\"},\"returns\":{\"_0\":\"Success indicator for whether each corresponding market was entered\"}},\"enterPool(uint96)\":{\"custom:error\":\"PoolDoesNotExist The specified pool ID does not exist.AlreadyInSelectedPool The user is already in the target pool.IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.LiquidityCheckFailed The user's liquidity is insufficient after switching pools.InactivePool The user is trying to enter inactive pool.\",\"custom:event\":\"PoolSelected Emitted after a successful pool switch.\",\"params\":{\"poolId\":\"The ID of the pool the user wants to enter.\"}},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow\",\"params\":{\"vTokenAddress\":\"The address of the asset to be removed\"},\"returns\":{\"_0\":\"Whether or not the account successfully exited the market\"}},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market\",\"returns\":{\"_0\":\"The list of market addresses\"}},\"getAssetsIn(address)\":{\"details\":\"Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools, all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\",\"params\":{\"account\":\"The address of the account to query\"},\"returns\":{\"_0\":\"assets A dynamic array of vToken markets the account has entered\"}},\"getCollateralFactor(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the collateral factor for\"},\"returns\":{\"_0\":\"The collateral factor for the vToken, scaled by 1e18\"}},\"getEffectiveLiquidationIncentive(address,address)\":{\"details\":\"The incentive is determined by the pool entered by the account and the specified vToken via `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\",\"params\":{\"account\":\"The account whose pool is used to determine the market's risk parameters\",\"vToken\":\"The address of the vToken market\"},\"returns\":{\"_0\":\"The liquidation Incentive for the vToken, scaled by 1e18\"}},\"getEffectiveLtvFactor(address,address,uint8)\":{\"details\":\"The value is determined by the pool entered by the account and the specified vToken via `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used. This value is used for account liquidity calculations and liquidation checks.\",\"params\":{\"account\":\"The account whose pool is used to determine the market's risk parameters.\",\"vToken\":\"The address of the vToken market.\",\"weightingStrategy\":\"The weighting strategy to use: - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\"},\"returns\":{\"_0\":\"factor The effective loan-to-value factor, scaled by 1e18.\"}},\"getLiquidationIncentive(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the liquidation Incentive for\"},\"returns\":{\"_0\":\"liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\"}},\"getLiquidationThreshold(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the liquidation threshold for\"},\"returns\":{\"_0\":\"The liquidation threshold for the vToken, scaled by 1e18\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getPoolVTokens(uint96)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the given pool ID do not exist.InvalidOperationForCorePool Reverts if called on the Core Pool.\",\"params\":{\"poolId\":\"The ID of the pool whose vTokens are being queried.\"},\"returns\":{\"_0\":\"An array of vToken addresses associated with the pool.\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"hasValidPoolBorrows(address,uint96)\":{\"params\":{\"account\":\"The address of the user attempting to switch pools.\",\"targetPoolId\":\"The pool ID the user wants to switch into.\"},\"returns\":{\"_0\":\"bool True if the switch is allowed, otherwise False.\"}},\"isMarketListed(address)\":{\"params\":{\"vToken\":\"The vToken Address of the market to check\"},\"returns\":{\"_0\":\"listed True if the (Core Pool, vToken) market is listed, otherwise false\"}},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"borrower\":\"Address of borrower whose collateral is being seized\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"liquidateVAICalculateSeizeTokens(address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"markets(address)\":{\"details\":\"Fetches the Market struct associated with the core pool and returns all relevant parameters.\",\"params\":{\"vToken\":\"The address of the vToken whose market configuration is to be fetched.\"},\"returns\":{\"collateralFactorMantissa\":\"The maximum borrowable percentage of collateral, in mantissa.\",\"isBorrowAllowed\":\"Whether borrowing is allowed in this market.\",\"isListed\":\"Whether the market is listed and enabled.\",\"isVenus\":\"Whether this market is eligible for VENUS rewards.\",\"liquidationIncentiveMantissa\":\"The max liquidation incentive allowed for this market, in mantissa.\",\"liquidationThresholdMantissa\":\"The threshold at which liquidation is triggered, in mantissa.\",\"marketPoolId\":\"The pool ID this market belongs to.\"}},\"poolMarkets(uint96,address)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the given pool ID do not exist.\",\"details\":\"Fetches the Market struct associated with the poolId and returns all relevant parameters.\",\"params\":{\"poolId\":\"The ID of the pool whose market configuration is being queried.\",\"vToken\":\"The address of the vToken whose market configuration is to be fetched.\"},\"returns\":{\"collateralFactorMantissa\":\"The maximum borrowable percentage of collateral, in mantissa.\",\"isBorrowAllowed\":\"Whether borrowing is allowed in this market.\",\"isListed\":\"Whether the market is listed and enabled.\",\"isVenus\":\"Whether this market is eligible for XVS rewards.\",\"liquidationIncentiveMantissa\":\"The liquidation incentive allowed for this market, in mantissa.\",\"liquidationThresholdMantissa\":\"The threshold at which liquidation is triggered, in mantissa.\",\"marketPoolId\":\"The pool ID this market belongs to.\"}},\"removePoolMarket(uint96,address)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts if called on the Core Pool.PoolMarketNotFound Reverts if the market is not listed in the pool.\",\"custom:event\":\"PoolMarketRemoved Emitted after a market is successfully removed from a pool.\",\"params\":{\"poolId\":\"The ID of the pool from which the market should be removed.\",\"vToken\":\"The address of the market token to remove.\"}},\"supportMarket(address)\":{\"params\":{\"vToken\":\"The address of the market (token) to list\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"unlistMarket(address)\":{\"details\":\"Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\",\"params\":{\"market\":\"The address of the market (vToken) to unlist\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (See enum Error for details)\"}},\"updateDelegate(address,bool)\":{\"params\":{\"approved\":\"Whether to grant (true) or revoke (false) the borrowing or redeeming rights\",\"delegate\":\"The address to update the rights for\"}}},\"title\":\"MarketFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DelegateUpdated(address,address,bool)\":{\"notice\":\"Emitted when the borrowing or redeeming delegate rights are updated for an account\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"MarketExited(address,address)\":{\"notice\":\"Emitted when an account exits a market\"},\"MarketListed(address)\":{\"notice\":\"Emitted when an admin supports a market\"},\"MarketUnlisted(address)\":{\"notice\":\"Emitted when an admin unlists a market\"},\"PoolCreated(uint96,string)\":{\"notice\":\"Emitted when a new pool is created\"},\"PoolMarketInitialized(uint96,address)\":{\"notice\":\"Emitted when a market is initialized in a pool\"},\"PoolMarketRemoved(uint96,address)\":{\"notice\":\"Emitted when a vToken market is removed from a pool\"},\"PoolSelected(address,uint96,uint96)\":{\"notice\":\"Emitted when a user enters or exits a pool (poolId = 0 means exit)\"}},\"kind\":\"user\",\"methods\":{\"_supportMarket(address)\":{\"notice\":\"Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"addPoolMarkets(uint96[],address[])\":{\"notice\":\"Batch initializes market entries with basic config.\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account has entered the specified vToken market in the Core Pool\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"createPool(string)\":{\"notice\":\"Creates a new pool with the given label.\"},\"enterMarketBehalf(address,address)\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"enterPool(uint96)\":{\"notice\":\"Allows a user to switch to a new pool (e.g., e-mode ).\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the vToken markets an account has entered in the Core Pool\"},\"getCollateralFactor(address)\":{\"notice\":\"Get the core pool collateral factor for a vToken\"},\"getEffectiveLiquidationIncentive(address,address)\":{\"notice\":\"Get the Effective Liquidation Incentive for a given account and market\"},\"getEffectiveLtvFactor(address,address,uint8)\":{\"notice\":\"Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\"},\"getLiquidationIncentive(address)\":{\"notice\":\"Get the core pool liquidation Incentive for a vToken\"},\"getLiquidationThreshold(address)\":{\"notice\":\"Get the core pool liquidation threshold for a vToken\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getPoolVTokens(uint96)\":{\"notice\":\"Returns the full list of vTokens for a given pool ID.\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"hasValidPoolBorrows(address,uint96)\":{\"notice\":\"Returns true if the user can switch to the given target pool, i.e., all markets they have borrowed from are also borrowable in the target pool.\"},\"isComptroller()\":{\"notice\":\"Indicator that this is a Comptroller contract (for inspection)\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"isMarketListed(address)\":{\"notice\":\"Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidateVAICalculateSeizeTokens(address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"markets(address)\":{\"notice\":\"Returns the market configuration for a vToken in the core pool (poolId = 0).\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"poolMarkets(uint96,address)\":{\"notice\":\"Returns the market configuration for a vToken from _poolMarkets.\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"removePoolMarket(uint96,address)\":{\"notice\":\"Removes a market (vToken) from the specified pool.\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"supportMarket(address)\":{\"notice\":\"Alias to _supportMarket to support the Isolated Lending Comptroller Interface\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"unlistMarket(address)\":{\"notice\":\"Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\"},\"updateDelegate(address,bool)\":{\"notice\":\"Grants or revokes the borrowing or redeeming delegate rights to / from an account If allowed, the delegate will be able to borrow funds on behalf of the sender Upon a delegated borrow, the delegate will receive the funds, and the borrower will see the debt on their account Upon a delegated redeem, the delegate will receive the redeemed amount and the approver will see a deduction in his vToken balance\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains functions regarding markets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/MarketFacet.sol\":\"MarketFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/MarketFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IMarketFacet } from \\\"../interfaces/IMarketFacet.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title MarketFacet\\n * @author Venus\\n * @dev This facet contains all the methods related to the market's management in the pool\\n * @notice This facet contract contains functions regarding markets\\n */\\ncontract MarketFacet is IMarketFacet, FacetBase {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(VToken indexed vToken);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account\\n event DelegateUpdated(address indexed approver, address indexed delegate, bool approved);\\n\\n /// @notice Emitted when an admin unlists a market\\n event MarketUnlisted(address indexed vToken);\\n\\n /// @notice Emitted when a market is initialized in a pool\\n event PoolMarketInitialized(uint96 indexed poolId, address indexed market);\\n\\n /// @notice Emitted when a user enters or exits a pool (poolId = 0 means exit)\\n event PoolSelected(address indexed account, uint96 previousPoolId, uint96 indexed newPoolId);\\n\\n /// @notice Emitted when a vToken market is removed from a pool\\n event PoolMarketRemoved(uint96 indexed poolId, address indexed vToken);\\n\\n /// @notice Emitted when a new pool is created\\n event PoolCreated(uint96 indexed poolId, string label);\\n\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() public pure returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Returns the vToken markets an account has entered in the Core Pool\\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\\n * @param account The address of the account to query\\n * @return assets A dynamic array of vToken markets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n uint256 len;\\n VToken[] memory _accountAssets = accountAssets[account];\\n uint256 _accountAssetsLength = _accountAssets.length;\\n\\n VToken[] memory assetsIn = new VToken[](_accountAssetsLength);\\n\\n for (uint256 i; i < _accountAssetsLength; ++i) {\\n Market storage market = getCorePoolMarket(address(_accountAssets[i]));\\n if (market.isListed) {\\n assetsIn[len] = _accountAssets[i];\\n ++len;\\n }\\n }\\n\\n assembly {\\n mstore(assetsIn, len)\\n }\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market\\n * @return The list of market addresses\\n */\\n function getAllMarkets() external view returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\\n address(this),\\n vTokenBorrowed,\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param borrower Address of borrower whose collateral is being seized\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n vTokenBorrowed,\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\\n address(this),\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns whether the given account has entered the specified vToken market in the Core Pool\\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the asset, otherwise false\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return getCorePoolMarket(address(vToken)).accountMembership[account];\\n }\\n\\n /**\\n * @notice Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken Address of the market to check\\n * @return listed True if the (Core Pool, vToken) market is listed, otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return getCorePoolMarket(address(vToken)).isListed;\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @dev Only callable by the account itself or an approved delegate\\n * @param onBehalf The address of the account entering the market\\n * @param vToken The address of the vToken market to enable for the account\\n * @return uint256 indicating the result (0 = success, non-zero = failure)\\n * @custom:error NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\\n */\\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256) {\\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\\n revert NotAnApprovedDelegate();\\n }\\n return uint256(addToMarketInternal(VToken(vToken), onBehalf));\\n }\\n\\n /**\\n * @notice Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\\n * @dev Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\\n * @param market The address of the market (vToken) to unlist\\n * @return uint256 0=success, otherwise a failure (See enum Error for details)\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n ensureAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = getCorePoolMarket(market);\\n\\n if (!_market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.UNLIST_MARKET_NOT_LISTED);\\n }\\n\\n require(actionPaused(market, Action.BORROW), \\\"borrow action is not paused\\\");\\n require(actionPaused(market, Action.MINT), \\\"mint action is not paused\\\");\\n require(actionPaused(market, Action.REDEEM), \\\"redeem action is not paused\\\");\\n require(actionPaused(market, Action.REPAY), \\\"repay action is not paused\\\");\\n require(actionPaused(market, Action.ENTER_MARKET), \\\"enter market action is not paused\\\");\\n require(actionPaused(market, Action.LIQUIDATE), \\\"liquidate action is not paused\\\");\\n require(actionPaused(market, Action.SEIZE), \\\"seize action is not paused\\\");\\n require(actionPaused(market, Action.TRANSFER), \\\"transfer action is not paused\\\");\\n require(actionPaused(market, Action.EXIT_MARKET), \\\"exit market action is not paused\\\");\\n\\n require(borrowCaps[market] == 0, \\\"borrow cap is not 0\\\");\\n require(supplyCaps[market] == 0, \\\"supply cap is not 0\\\");\\n\\n require(_market.collateralFactorMantissa == 0, \\\"collateral factor is not 0\\\");\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow\\n * @param vTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address vTokenAddress) external returns (uint256) {\\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = getCorePoolMarket(address(vToken));\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n uint256 i;\\n for (; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n userAssetList[i] = userAssetList[len - 1];\\n userAssetList.pop();\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(i < len);\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Alias to _supportMarket to support the Isolated Lending Comptroller Interface\\n * @param vToken The address of the market (token) to list\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function supportMarket(VToken vToken) external returns (uint256) {\\n return __supportMarket(vToken);\\n }\\n\\n /**\\n * @notice Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\\n * @dev Allows a privileged role to add and list markets to the Comptroller\\n * @param vToken The address of the vToken market to list in the Core Pool\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(VToken vToken) external returns (uint256) {\\n return __supportMarket(vToken);\\n }\\n\\n /**\\n * @notice Grants or revokes the borrowing or redeeming delegate rights to / from an account\\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\\n * will see the debt on their account\\n * Upon a delegated redeem, the delegate will receive the redeemed amount and the approver\\n * will see a deduction in his vToken balance\\n * @param delegate The address to update the rights for\\n * @param approved Whether to grant (true) or revoke (false) the borrowing or redeeming rights\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n require(approvedDelegates[msg.sender][delegate] != approved, \\\"Delegation status unchanged\\\");\\n\\n _updateDelegate(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Allows a user to switch to a new pool (e.g., e-mode ).\\n * @param poolId The ID of the pool the user wants to enter.\\n * @custom:error PoolDoesNotExist The specified pool ID does not exist.\\n * @custom:error AlreadyInSelectedPool The user is already in the target pool.\\n * @custom:error IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.\\n * @custom:error LiquidityCheckFailed The user's liquidity is insufficient after switching pools.\\n * @custom:error InactivePool The user is trying to enter inactive pool.\\n * @custom:event PoolSelected Emitted after a successful pool switch.\\n */\\n function enterPool(uint96 poolId) external {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n if (poolId == userPoolId[msg.sender]) {\\n revert AlreadyInSelectedPool();\\n }\\n\\n if (poolId != corePoolId && !pools[poolId].isActive) {\\n revert InactivePool(poolId);\\n }\\n\\n if (!hasValidPoolBorrows(msg.sender, poolId)) {\\n revert IncompatibleBorrowedAssets();\\n }\\n\\n emit PoolSelected(msg.sender, userPoolId[msg.sender], poolId);\\n\\n userPoolId[msg.sender] = poolId;\\n\\n (uint256 error, , uint256 shortfall) = _getAccountLiquidity(msg.sender, WeightFunction.USE_COLLATERAL_FACTOR);\\n\\n if (error != 0 || shortfall > 0) {\\n revert LiquidityCheckFailed(error, shortfall);\\n }\\n }\\n\\n /**\\n * @notice Creates a new pool with the given label.\\n * @param label name for the pool (must be non-empty).\\n * @return poolId The incremental unique identifier of the newly created pool.\\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string.\\n * @custom:event PoolCreated Emitted after successfully creating a new pool.\\n */\\n function createPool(string memory label) external returns (uint96) {\\n ensureAllowed(\\\"createPool(string)\\\");\\n\\n if (bytes(label).length == 0) {\\n revert EmptyPoolLabel();\\n }\\n\\n uint96 poolId = ++lastPoolId;\\n PoolData storage newPool = pools[poolId];\\n newPool.label = label;\\n newPool.isActive = true;\\n\\n emit PoolCreated(poolId, label);\\n return poolId;\\n }\\n\\n /**\\n * @notice Batch initializes market entries with basic config.\\n * @param poolIds Array of pool IDs.\\n * @param vTokens Array of market (vToken) addresses.\\n * @custom:error ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:error MarketNotListedInCorePool Reverts if the market is not listed in the core pool.\\n * @custom:error MarketAlreadyListed Reverts if the given market is already listed in the specified pool.\\n * @custom:error InactivePool Reverts if attempted to add markets to an inactive pool.\\n * @custom:event PoolMarketInitialized Emitted after successfully initializing a market in a pool.\\n */\\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external {\\n ensureAllowed(\\\"addPoolMarkets(uint96[],address[])\\\");\\n\\n uint256 len = poolIds.length;\\n if (len == 0 || len != vTokens.length) {\\n revert ArrayLengthMismatch();\\n }\\n\\n for (uint256 i; i < len; i++) {\\n _addPoolMarket(poolIds[i], vTokens[i]);\\n }\\n }\\n\\n /**\\n * @notice Removes a market (vToken) from the specified pool.\\n * @param poolId The ID of the pool from which the market should be removed.\\n * @param vToken The address of the market token to remove.\\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\\n * @custom:error PoolMarketNotFound Reverts if the market is not listed in the pool.\\n * @custom:event PoolMarketRemoved Emitted after a market is successfully removed from a pool.\\n */\\n function removePoolMarket(uint96 poolId, address vToken) external {\\n ensureAllowed(\\\"removePoolMarket(uint96,address)\\\");\\n\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\\n if (!_poolMarkets[index].isListed) {\\n revert PoolMarketNotFound(poolId, vToken);\\n }\\n\\n address[] storage assets = pools[poolId].vTokens;\\n\\n uint256 length = assets.length;\\n for (uint256 i; i < length; i++) {\\n if (assets[i] == vToken) {\\n assets[i] = assets[length - 1];\\n assets.pop();\\n break;\\n }\\n }\\n\\n delete _poolMarkets[index];\\n\\n emit PoolMarketRemoved(poolId, vToken);\\n }\\n\\n /**\\n * @notice Get the core pool collateral factor for a vToken\\n * @param vToken The address of the vToken to get the collateral factor for\\n * @return The collateral factor for the vToken, scaled by 1e18\\n */\\n function getCollateralFactor(address vToken) external view returns (uint256) {\\n (uint256 cf, , ) = getLiquidationParams(corePoolId, vToken);\\n return cf;\\n }\\n\\n /**\\n * @notice Get the core pool liquidation threshold for a vToken\\n * @param vToken The address of the vToken to get the liquidation threshold for\\n * @return The liquidation threshold for the vToken, scaled by 1e18\\n */\\n function getLiquidationThreshold(address vToken) external view returns (uint256) {\\n (, uint256 lt, ) = getLiquidationParams(corePoolId, vToken);\\n return lt;\\n }\\n\\n /**\\n * @notice Get the core pool liquidation Incentive for a vToken\\n * @param vToken The address of the vToken to get the liquidation Incentive for\\n * @return liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\\n */\\n function getLiquidationIncentive(address vToken) external view returns (uint256) {\\n (, , uint256 li) = getLiquidationParams(corePoolId, vToken);\\n return li;\\n }\\n\\n /**\\n * @notice Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\\n * @dev The value is determined by the pool entered by the account and the specified vToken via\\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used.\\n * This value is used for account liquidity calculations and liquidation checks.\\n * @param account The account whose pool is used to determine the market's risk parameters.\\n * @param vToken The address of the vToken market.\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return factor The effective loan-to-value factor, scaled by 1e18.\\n */\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256) {\\n (uint256 cf, uint256 lt, ) = getLiquidationParams(userPoolId[account], vToken);\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) return cf;\\n else if (weightingStrategy == WeightFunction.USE_LIQUIDATION_THRESHOLD) return lt;\\n else revert InvalidWeightingStrategy(weightingStrategy);\\n }\\n\\n /**\\n * @notice Get the Effective Liquidation Incentive for a given account and market\\n * @dev The incentive is determined by the pool entered by the account and the specified vToken via\\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\\n * @param account The account whose pool is used to determine the market's risk parameters\\n * @param vToken The address of the vToken market\\n * @return The liquidation Incentive for the vToken, scaled by 1e18\\n */\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256) {\\n (, , uint256 li) = getLiquidationParams(userPoolId[account], vToken);\\n return li;\\n }\\n\\n /**\\n * @notice Returns the full list of vTokens for a given pool ID.\\n * @param poolId The ID of the pool whose vTokens are being queried.\\n * @return An array of vToken addresses associated with the pool.\\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\\n */\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory) {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n return pools[poolId].vTokens;\\n }\\n\\n /**\\n * @notice Returns the market configuration for a vToken in the core pool (poolId = 0).\\n * @dev Fetches the Market struct associated with the core pool and returns all relevant parameters.\\n * @param vToken The address of the vToken whose market configuration is to be fetched.\\n * @return isListed Whether the market is listed and enabled.\\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\\n * @return isVenus Whether this market is eligible for VENUS rewards.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The max liquidation incentive allowed for this market, in mantissa.\\n * @return marketPoolId The pool ID this market belongs to.\\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\\n */\\n function markets(\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n )\\n {\\n return poolMarkets(corePoolId, vToken);\\n }\\n\\n /**\\n * @notice Returns the market configuration for a vToken from _poolMarkets.\\n * @dev Fetches the Market struct associated with the poolId and returns all relevant parameters.\\n * @param poolId The ID of the pool whose market configuration is being queried.\\n * @param vToken The address of the vToken whose market configuration is to be fetched.\\n * @return isListed Whether the market is listed and enabled.\\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\\n * @return isVenus Whether this market is eligible for XVS rewards.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\\n * @return marketPoolId The pool ID this market belongs to.\\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\\n */\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n public\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n )\\n {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n PoolMarketId key = getPoolMarketIndex(poolId, vToken);\\n Market storage m = _poolMarkets[key];\\n\\n return (\\n m.isListed,\\n m.collateralFactorMantissa,\\n m.isVenus,\\n m.liquidationThresholdMantissa,\\n m.liquidationIncentiveMantissa,\\n m.poolId,\\n m.isBorrowAllowed\\n );\\n }\\n\\n /**\\n * @notice Returns true if the user can switch to the given target pool, i.e.,\\n * all markets they have borrowed from are also borrowable in the target pool.\\n * @param account The address of the user attempting to switch pools.\\n * @param targetPoolId The pool ID the user wants to switch into.\\n * @return bool True if the switch is allowed, otherwise False.\\n */\\n function hasValidPoolBorrows(address account, uint96 targetPoolId) public view returns (bool) {\\n VToken[] memory assets = accountAssets[account];\\n if (targetPoolId != corePoolId && mintedVAIs[account] > 0) {\\n return false;\\n }\\n\\n for (uint256 i; i < assets.length; i++) {\\n VToken vToken = assets[i];\\n PoolMarketId index = getPoolMarketIndex(targetPoolId, address(vToken));\\n\\n if (!_poolMarkets[index].isBorrowAllowed) {\\n if (vToken.borrowBalanceStored(account) > 0) {\\n return false;\\n }\\n }\\n }\\n return true;\\n }\\n\\n function _updateDelegate(address approver, address delegate, bool approved) internal {\\n approvedDelegates[approver][delegate] = approved;\\n emit DelegateUpdated(approver, delegate, approved);\\n }\\n\\n function _addMarketInternal(VToken vToken) internal {\\n uint256 allMarketsLength = allMarkets.length;\\n for (uint256 i; i < allMarketsLength; ++i) {\\n require(allMarkets[i] != vToken, \\\"already added\\\");\\n }\\n allMarkets.push(vToken);\\n }\\n\\n function _initializeMarket(address vToken) internal {\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = venusInitialIndex;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = venusInitialIndex;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n function __supportMarket(VToken vToken) internal returns (uint256) {\\n ensureAllowed(\\\"_supportMarket(address)\\\");\\n\\n if (getCorePoolMarket(address(vToken)).isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n vToken.isVToken(); // Sanity check to make sure its really a VToken\\n\\n // Note that isVenus is not in active use anymore\\n Market storage newMarket = getCorePoolMarket(address(vToken));\\n newMarket.isListed = true;\\n newMarket.isVenus = false;\\n newMarket.collateralFactorMantissa = 0;\\n\\n _addMarketInternal(vToken);\\n _initializeMarket(address(vToken));\\n\\n emit MarketListed(vToken);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n function _addPoolMarket(uint96 poolId, address vToken) internal {\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (!pools[poolId].isActive) revert InactivePool(poolId);\\n\\n // Core Pool Index\\n PoolMarketId index = getPoolMarketIndex(corePoolId, vToken);\\n if (!_poolMarkets[index].isListed) revert MarketNotListedInCorePool();\\n\\n // Pool Index\\n index = getPoolMarketIndex(poolId, vToken);\\n if (_poolMarkets[index].isListed) revert MarketAlreadyListed(poolId, vToken);\\n\\n Market storage m = _poolMarkets[index];\\n m.poolId = poolId;\\n m.isListed = true;\\n\\n pools[poolId].vTokens.push(vToken);\\n\\n emit PoolMarketInitialized(poolId, vToken);\\n }\\n\\n /**\\n * @notice Returns only the core risk parameters (CF, LI, LT) for a vToken in a specific pool.\\n * @dev If the pool is inactive, or if the vToken is not configured in the given pool and\\n * `allowCorePoolFallback` is enabled, falls back to the core pool (poolId = 0) values.\\n * @return collateralFactorMantissa The max borrowable percentage of collateral, in mantissa.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\\n */\\n function getLiquidationParams(\\n uint96 poolId,\\n address vToken\\n )\\n internal\\n view\\n returns (\\n uint256 collateralFactorMantissa,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa\\n )\\n {\\n PoolData storage pool = pools[poolId];\\n Market storage market;\\n\\n if (poolId == corePoolId || !pool.isActive) {\\n market = getCorePoolMarket(vToken);\\n } else {\\n PoolMarketId poolKey = getPoolMarketIndex(poolId, vToken);\\n Market storage poolMarket = _poolMarkets[poolKey];\\n market = (!poolMarket.isListed && pool.allowCorePoolFallback) ? getCorePoolMarket(vToken) : poolMarket;\\n }\\n\\n return (\\n market.collateralFactorMantissa,\\n market.liquidationThresholdMantissa,\\n market.liquidationIncentiveMantissa\\n );\\n }\\n}\\n\",\"keccak256\":\"0x168e841b9538dd463ebe73235cbb9a15be601b476c1efbfae81d38dcdb989421\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IMarketFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./IFacetBase.sol\\\";\\n\\ninterface IMarketFacet {\\n function isComptroller() external pure returns (bool);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function checkMembership(address account, VToken vToken) external view returns (bool);\\n\\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256);\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n function _supportMarket(VToken vToken) external returns (uint256);\\n\\n function supportMarket(VToken vToken) external returns (uint256);\\n\\n function isMarketListed(VToken vToken) external view returns (bool);\\n\\n function getAssetsIn(address account) external view returns (VToken[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function updateDelegate(address delegate, bool allowBorrows) external;\\n\\n function unlistMarket(address market) external returns (uint256);\\n\\n function createPool(string memory label) external returns (uint96);\\n\\n function enterPool(uint96 poolId) external;\\n\\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external;\\n\\n function removePoolMarket(uint96 poolId, address vToken) external;\\n\\n function markets(\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function hasValidPoolBorrows(address user, uint96 targetPoolId) external view returns (bool);\\n\\n function getCollateralFactor(address vToken) external view returns (uint256);\\n\\n function getLiquidationThreshold(address vToken) external view returns (uint256);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x11118e9ea5b6c8df34d55ae85f4310ef9f6a7590b3a2202fbc7a2bb0b8572699\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506138168061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061044d575f3560e01c806396c9906411610242578063cab4f84c11610140578063e0f6123d116100bf578063f02fdf9711610084578063f02fdf9714610b48578063f445d70314610b5b578063f851a44014610b88578063f968273214610b9a578063fa6331d814610bad575f80fd5b8063e0f6123d14610ac0578063e37d4b7914610ae2578063e85a296014610b19578063e875544614610b2c578063ede4edd014610b35575f80fd5b8063d585c3c611610105578063d585c3c614610a61578063d686e9ee14610a74578063dce1544914610a87578063dcfbc0c714610a9a578063ddbf54fd14610aad575f80fd5b8063cab4f84c1461088c578063d0d1303614610a21578063d137f36e14610a34578063d3270f9914610a47578063d463654c14610a5a575f80fd5b8063b8324c7c116101cc578063c299823811610191578063c29982381461099a578063c488847b146109ba578063c5b4db55146109cd578063c5f956af146109fb578063c7ee005e14610a0e575f80fd5b8063b8324c7c146108f3578063bb82aa5e1461094e578063bbb8864a14610961578063bec04f7214610980578063bf32442d14610989575f80fd5b8063a78dc77511610212578063a78dc7751461089f578063abfceffc146108b2578063afd3783b146108c5578063b0772d0b146108d8578063b2eafc39146108e0575f80fd5b806396c99064146108445780639bb27d6214610866578063a657e57914610879578063a76b3fda1461088c575f80fd5b80634a5844321161034f5780637d172bd5116102d95780638c1ac18a1161029e5780638c1ac18a146107e05780638e8f294b146108025780639254f5e514610815578063929fe9a11461082857806394b2294b1461083b575f80fd5b80637d172bd5146107795780637dc0d1d01461078c5780637fb8e8cd1461079f57806389c13be0146107ac5780638a7dc165146107c1575f80fd5b806363e0d6341161031f57806363e0d634146106eb578063719f701b1461070b578063737690991461071457806376551383146107545780637b86e42c14610766575f80fd5b80634a584432146106875780634d99c776146106a657806352d84d1e146106b95780635dd3fc9d146106cc575f80fd5b806321af4569116103db5780633093c11e116103a05780633093c11e146105d05780633d98a1e51461062a5780634088c73e1461063d57806341a18d2c1461064a578063425fad5814610674575f80fd5b806321af45691461054d578063236175851461057857806324a3d6221461058b578063267822471461059e5780632bc7e29e146105b1575f80fd5b806308e0225c1161042157806308e0225c146104b25780630db4b4e5146104dc5780630ef332ca146104e557806310b983381461050d57806319ef3e8b1461053a575f80fd5b80627e3dd21461045157806302c3bcbb1461046957806304ef9d58146104965780630686dab61461049f575b5f80fd5b60015b60405190151581526020015b60405180910390f35b610488610477366004612fa8565b60276020525f908152604090205481565b604051908152602001610460565b61048860225481565b6104886104ad366004612fa8565b610bb6565b6104886104c0366004612fc3565b601360209081525f928352604080842090915290825290205481565b610488601d5481565b6104f86104f3366004612ffa565b61107c565b60408051928352602083019190915201610460565b61045461051b366004612fc3565b602c60209081525f928352604080842090915290825290205460ff1681565b610488610548366004613048565b611119565b601e54610560906001600160a01b031681565b6040516001600160a01b039091168152602001610460565b610488610586366004612fa8565b6111ab565b600a54610560906001600160a01b031681565b600154610560906001600160a01b031681565b6104886105bf366004612fa8565b60166020525f908152604090205481565b6105e36105de3660046130ae565b6111c1565b604080519715158852602088019690965293151594860194909452606085019190915260808401526001600160601b0390911660a0830152151560c082015260e001610460565b610454610638366004612fa8565b611286565b6018546104549060ff1681565b610488610658366004612fc3565b601260209081525f928352604080842090915290825290205481565b6018546104549062010000900460ff1681565b610488610695366004612fa8565b601f6020525f908152604090205481565b6104886106b43660046130ae565b61129a565b6105606106c73660046130c8565b6112bb565b6104886106da366004612fa8565b602b6020525f908152604090205481565b6106fe6106f93660046130df565b6112e3565b60405161046091906130f8565b610488601c5481565b61073c610722366004612fa8565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610460565b60185461045490610100900460ff1681565b610488610774366004612fa8565b6113bc565b601b54610560906001600160a01b031681565b600454610560906001600160a01b031681565b6039546104549060ff1681565b6107bf6107ba366004613185565b6113d1565b005b6104886107cf366004612fa8565b60146020525f908152604090205481565b6104546107ee366004612fa8565b602d6020525f908152604090205460ff1681565b6105e3610810366004612fa8565b61148e565b601554610560906001600160a01b031681565b610454610836366004612fc3565b6114b6565b61048860075481565b6108576108523660046130df565b6114e5565b6040516104609392919061321a565b602554610560906001600160a01b031681565b60375461073c906001600160601b031681565b61048861089a366004612fa8565b611592565b6104f86108ad366004613243565b61159c565b6106fe6108c0366004612fa8565b611629565b6104886108d3366004612fc3565b611786565b6106fe6117bd565b602054610560906001600160a01b031681565b61092a610901366004612fa8565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610460565b600254610560906001600160a01b031681565b61048861096f366004612fa8565b602a6020525f908152604090205481565b61048860175481565b6033546001600160a01b0316610560565b6109ad6109a836600461326d565b61181d565b60405161046091906132ac565b6104f86109c83660046132e3565b6118d6565b6109e36ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b039091168152602001610460565b602154610560906001600160a01b031681565b603154610560906001600160a01b031681565b61073c610a2f366004613335565b61196a565b6107bf610a423660046130ae565b611a70565b602654610560906001600160a01b031681565b61073c5f81565b610488610a6f366004612fc3565b611cca565b610488610a82366004612fa8565b611d40565b610560610a95366004613243565b611d55565b600354610560906001600160a01b031681565b6107bf610abb3660046133ed565b611d89565b610454610ace366004612fa8565b60386020525f908152604090205460ff1681565b61092a610af0366004612fa8565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b610454610b27366004613419565b611e1b565b61048860055481565b610488610b43366004612fa8565b611e5f565b610454610b56366004613448565b612108565b610454610b69366004612fc3565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610560906001600160a01b031681565b6107bf610ba83660046130df565b612297565b610488601a5481565b5f610bed60405180604001604052806015815260200174756e6c6973744d61726b657428616464726573732960581b81525061245b565b5f610bf78361250b565b805490915060ff16610c1657610c0f6009601861252d565b9392505050565b610c21836002611e1b565b610c725760405162461bcd60e51b815260206004820152601b60248201527f626f72726f7720616374696f6e206973206e6f7420706175736564000000000060448201526064015b60405180910390fd5b610c7c835f611e1b565b610cc85760405162461bcd60e51b815260206004820152601960248201527f6d696e7420616374696f6e206973206e6f7420706175736564000000000000006044820152606401610c69565b610cd3836001611e1b565b610d1f5760405162461bcd60e51b815260206004820152601b60248201527f72656465656d20616374696f6e206973206e6f742070617573656400000000006044820152606401610c69565b610d2a836003611e1b565b610d765760405162461bcd60e51b815260206004820152601a60248201527f726570617920616374696f6e206973206e6f74207061757365640000000000006044820152606401610c69565b610d81836007611e1b565b610dd75760405162461bcd60e51b815260206004820152602160248201527f656e746572206d61726b657420616374696f6e206973206e6f742070617573656044820152601960fa1b6064820152608401610c69565b610de2836005611e1b565b610e2e5760405162461bcd60e51b815260206004820152601e60248201527f6c697175696461746520616374696f6e206973206e6f742070617573656400006044820152606401610c69565b610e39836004611e1b565b610e855760405162461bcd60e51b815260206004820152601a60248201527f7365697a6520616374696f6e206973206e6f74207061757365640000000000006044820152606401610c69565b610e90836006611e1b565b610edc5760405162461bcd60e51b815260206004820152601d60248201527f7472616e7366657220616374696f6e206973206e6f74207061757365640000006044820152606401610c69565b610ee7836008611e1b565b610f335760405162461bcd60e51b815260206004820181905260248201527f65786974206d61726b657420616374696f6e206973206e6f74207061757365646044820152606401610c69565b6001600160a01b0383165f908152601f602052604090205415610f8e5760405162461bcd60e51b81526020600482015260136024820152720626f72726f7720636170206973206e6f74203606c1b6044820152606401610c69565b6001600160a01b0383165f9081526027602052604090205415610fe95760405162461bcd60e51b81526020600482015260136024820152720737570706c7920636170206973206e6f74203606c1b6044820152606401610c69565b60018101541561103b5760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206973206e6f7420300000000000006044820152606401610c69565b805460ff191681556040516001600160a01b038416907f302feb03efd5741df80efe7f97f5d93d74d46a542a3d312d0faae64fa1f3e0e9905f90a25f610c0f565b602654604051630a5d5a0560e41b81526001600160a01b03868116600483015230602483015285811660448301528481166064830152608482018490525f92839283928392169063a5d5a0509060a4016040805180830381865afa1580156110e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110a919061348f565b90999098509650505050505050565b6001600160a01b0383165f9081526035602052604081205481908190611148906001600160601b0316866125a4565b5090925090505f8460018111156111615761116161347b565b0361116e57509050610c0f565b60018460018111156111825761118261347b565b03611190579150610c0f9050565b83604051632f03799f60e11b8152600401610c6991906134d1565b5f806111b75f846125a4565b5090949350505050565b5f805f805f805f60375f9054906101000a90046001600160601b03166001600160601b0316896001600160601b0316111561121a57604051632db8671b60e11b81526001600160601b038a166004820152602401610c69565b5f6112258a8a61129a565b5f9081526009602052604090208054600182015460038301546004840154600585015460069095015460ff9485169d50929b50908316995097509195506001600160601b0382169450600160601b9091041691505092959891949750929550565b5f6112908261250b565b5460ff1692915050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d81815481106112ca575f80fd5b5f918252602090912001546001600160a01b0316905081565b6037546060906001600160601b03908116908316111561132157604051632db8671b60e11b81526001600160601b0383166004820152602401610c69565b6001600160601b03821661134857604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f90815260366020908152604091829020600101805483518184028101840190945280845290918301828280156113b057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611392575b50505050509050919050565b5f806113c85f846125a4565b50949350505050565b6113f26040518060600160405280602281526020016137bf6022913961245b565b828015806114005750808214155b1561141e5760405163512509d360e11b815260040160405180910390fd5b5f5b818110156114865761147e86868381811061143d5761143d6134df565b905060200201602081019061145291906130df565b858584818110611464576114646134df565b90506020020160208101906114799190612fa8565b612656565b600101611420565b505050505050565b5f805f805f805f61149f5f896111c1565b959e949d50929b5090995097509550909350915050565b5f6114c08261250b565b6001600160a01b03939093165f90815260029093016020525050604090205460ff1690565b60366020525f90815260409020805481906114ff906134f3565b80601f016020809104026020016040519081016040528092919081815260200182805461152b906134f3565b80156115765780601f1061154d57610100808354040283529160200191611576565b820191905f5260205f20905b81548152906001019060200180831161155957829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6112b582612839565b6026546040516304f65f8b60e21b81523060048201526001600160a01b038481166024830152604482018490525f9283928392839216906313d97e2c906064016040805180830381865afa1580156115f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061161a919061348f565b909450925050505b9250929050565b6001600160a01b0381165f908152600860209081526040808320805482518185028101850190935280835260609493849392919083018282801561169457602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611676575b505050505090505f815190505f8167ffffffffffffffff8111156116ba576116ba613321565b6040519080825280602002602001820160405280156116e3578160200160208202803683370190505b5090505f5b82811015611779575f611713858381518110611706576117066134df565b602002602001015161250b565b805490915060ff161561177057848281518110611732576117326134df565b602002602001015183878151811061174c5761174c6134df565b6001600160a01b039092166020928302919091019091015261176d8661353f565b95505b506001016116e8565b5092835250909392505050565b6001600160a01b0382165f9081526035602052604081205481906117b3906001600160601b0316846125a4565b9695505050505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561181357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116117f5575b5050505050905090565b6060815f8167ffffffffffffffff81111561183a5761183a613321565b604051908082528060200260200182016040528015611863578160200160208202803683370190505b5090505f5b828110156113c8576118a0868683818110611885576118856134df565b905060200201602081019061189a9190612fa8565b3361296d565b60148111156118b1576118b161347b565b8282815181106118c3576118c36134df565b6020908102919091010152600101611868565b602654604051630779996560e11b81523060048201526001600160a01b0385811660248301528481166044830152606482018490525f928392839283921690630ef332ca906084016040805180830381865afa158015611938573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061195c919061348f565b909890975095505050505050565b5f61199e60405180604001604052806012815260200171637265617465506f6f6c28737472696e672960701b81525061245b565b81515f036119bf5760405163522e397360e11b815260040160405180910390fd5b603780545f919082906119da906001600160601b0316613557565b82546001600160601b038083166101009490940a848102910219909116179092555f90815260366020526040902090915080611a1685826135c7565b5060028101805460ff191660011790556040516001600160601b038316907fc419386a8582a5374f4db03fdbb9fd99c73ef32d6ce9fc3a8c249e97bf31f9af90611a61908790613683565b60405180910390a25092915050565b611aae6040518060400160405280602081526020017f72656d6f7665506f6f6c4d61726b65742875696e7439362c616464726573732981525061245b565b6001600160601b038216611ad557604051630203217b60e61b815260040160405180910390fd5b5f611ae0838361129a565b5f8181526009602052604090205490915060ff16611b2b576040516338ddb96b60e11b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c69565b6001600160601b0383165f908152603660205260408120600101805490915b81811015611c3857846001600160a01b0316838281548110611b6e57611b6e6134df565b5f918252602090912001546001600160a01b031603611c305782611b93600184613695565b81548110611ba357611ba36134df565b905f5260205f20015f9054906101000a90046001600160a01b0316838281548110611bd057611bd06134df565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480611c0b57611c0b6136a8565b5f8281526020902081015f1990810180546001600160a01b0319169055019055611c38565b600101611b4a565b505f83815260096020526040808220805460ff199081168255600182018490556003820180549091169055600481018390556005810183905560060180546cffffffffffffffffffffffffff19169055516001600160a01b038616916001600160601b038816917fc8bef274db6d8c804aba68a69e64268bcfe7dd0aead2efcec0cac73a2df56e129190a35050505050565b5f336001600160a01b03841614801590611d0757506001600160a01b0383165f908152602c6020908152604080832033845290915290205460ff16155b15611d25576040516337248ad960e01b815260040160405180910390fd5b611d2f828461296d565b6014811115610c0f57610c0f61347b565b5f80611d4c5f846125a4565b95945050505050565b6008602052815f5260405f208181548110611d6e575f80fd5b5f918252602090912001546001600160a01b03169150829050565b611d9282612a40565b335f908152602c602090815260408083206001600160a01b038616845290915290205481151560ff909116151503611e0c5760405162461bcd60e51b815260206004820152601b60248201527f44656c65676174696f6e2073746174757320756e6368616e67656400000000006044820152606401610c69565b611e17338383612a8e565b5050565b6001600160a01b0382165f90815260296020526040812081836008811115611e4557611e4561347b565b815260208101919091526040015f205460ff169392505050565b5f611e6b826008612afa565b6040516361bfb47160e11b815233600482015282905f90819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa158015611eb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ed991906136bc565b50925092509250825f14611f2f5760405162461bcd60e51b815260206004820152601960248201527f6765744163636f756e74536e617073686f74206661696c6564000000000000006044820152606401610c69565b8015611f41576117b3600c600261252d565b5f611f4d873385612b44565b90508015611f6d57611f62600e600383612beb565b979650505050505050565b5f611f778661250b565b335f90815260028201602052604090205490915060ff16611f9f575f98975050505050505050565b335f9081526002820160209081526040808320805460ff1916905560089091528120805490915b818110156120b457886001600160a01b0316838281548110611fea57611fea6134df565b5f918252602090912001546001600160a01b0316036120ac578261200f600184613695565b8154811061201f5761201f6134df565b905f5260205f20015f9054906101000a90046001600160a01b031683828154811061204c5761204c6134df565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480612087576120876136a8565b5f8281526020902081015f1990810180546001600160a01b03191690550190556120b4565b600101611fc6565b8181106120c3576120c36136ef565b60405133906001600160a01b038b16907fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d905f90a35f9b9a5050505050505050505050565b6001600160a01b0382165f9081526008602090815260408083208054825181850281018501909352808352849383018282801561216c57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161214e575b50939450505050506001600160601b038316158015906121a257506001600160a01b0384165f9081526016602052604090205415155b156121b0575f9150506112b5565b5f5b815181101561228c575f8282815181106121ce576121ce6134df565b602002602001015190505f6121e3868361129a565b5f81815260096020526040902060060154909150600160601b900460ff16612282576040516395dd919360e01b81526001600160a01b0388811660048301525f91908416906395dd919390602401602060405180830381865afa15801561224c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122709190613703565b1115612282575f9450505050506112b5565b50506001016121b2565b506001949350505050565b6037546001600160601b0390811690821611156122d257604051632db8671b60e11b81526001600160601b0382166004820152602401610c69565b335f908152603560205260409020546001600160601b039081169082160361230d57604051631c9d4f3960e31b815260040160405180910390fd5b6001600160601b0381161580159061234057506001600160601b0381165f9081526036602052604090206002015460ff16155b1561236957604051632da4cc0560e01b81526001600160601b0382166004820152602401610c69565b6123733382612108565b6123905760405163592ec11d60e01b815260040160405180910390fd5b335f818152603560209081526040918290205491516001600160601b03928316815291841692917f9181876220501cdac3aa7278fd34e9bd150c30a27b6ed95458fe859761b071f7910160405180910390a3335f81815260356020526040812080546bffffffffffffffffffffffff19166001600160601b03851617905590819061241b9082612c6a565b9250509150815f14158061242e57505f81115b156124565760405163c978466160e01b81526004810183905260248101829052604401610c69565b505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab9061248d903390859060040161371a565b602060405180830381865afa1580156124a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124cc919061373d565b6125085760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610c69565b50565b5f60095f6125195f8561129a565b81526020019081526020015f209050919050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360148111156125615761256161347b565b83601a8111156125735761257361347b565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610c0f57610c0f61347b565b6001600160601b0382165f818152603660205260408120909182918291829015806125d45750600282015460ff16155b156125e9576125e28661250b565b9050612638565b5f6125f4888861129a565b5f81815260096020526040902080549192509060ff1615801561262057506002840154610100900460ff165b61262a5780612633565b6126338861250b565b925050505b80600101548160040154826005015494509450945050509250925092565b6001600160601b03821661267d57604051630203217b60e61b815260040160405180910390fd5b6037546001600160601b0390811690831611156126b857604051632db8671b60e11b81526001600160601b0383166004820152602401610c69565b6001600160601b0382165f9081526036602052604090206002015460ff166126fe57604051632da4cc0560e01b81526001600160601b0383166004820152602401610c69565b5f6127095f8361129a565b5f8181526009602052604090205490915060ff1661273a576040516386dccab760e01b815260040160405180910390fd5b612744838361129a565b5f8181526009602052604090205490915060ff16156127905760405163d9d72f2b60e01b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c69565b5f8181526009602090815260408083206006810180546bffffffffffffffffffffffff19166001600160601b038916908117909155815460ff19166001908117835581865260368552838620810180549182018155865293852090930180546001600160a01b0319166001600160a01b038816908117909155915190939192917f2159e9508e372ac69e1047a124c5478445206066e5d7df7e4214a1986cd78c8091a350505050565b5f6128786040518060400160405280601781526020017f5f737570706f72744d61726b657428616464726573732900000000000000000081525061245b565b6128818261250b565b5460ff1615612896576112b5600a601161252d565b816001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128f6919061373d565b505f6129018361250b565b8054600160ff19918216811783556003830180549092169091555f90820155905061292b83612ca2565b61293483612d78565b6040516001600160a01b038416907fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f905f90a25f610c0f565b5f612979836007612afa565b5f6129838461250b565b905061298e81612e3a565b6001600160a01b0383165f90815260028201602052604090205460ff16156129b9575f9150506112b5565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b6001600160a01b0381166125085760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610c69565b6001600160a01b038381165f818152602c6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fcb325b7784f78486e42849c7a50b8c5ee008d00cd90e108a58912c0fcb6288b4910160405180910390a3505050565b612b048282611e1b565b15611e175760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610c69565b5f612b56612b518561250b565b612e3a565b612b5f8461250b565b6001600160a01b0384165f908152600291909101602052604090205460ff16612b8957505f610c0f565b5f80612b988587865f80612e7f565b9193509091505f9050826014811115612bb357612bb361347b565b14612bd357816014811115612bca57612bca61347b565b92505050610c0f565b8015612be0576004612bca565b5f9695505050505050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846014811115612c1f57612c1f61347b565b84601a811115612c3157612c3161347b565b604080519283526020830191909152810184905260600160405180910390a1836014811115612c6257612c6261347b565b949350505050565b5f805f805f80612c7d885f805f8b612e7f565b925092509250826014811115612c9557612c9561347b565b9891975095509350505050565b600d545f5b81811015612d2557826001600160a01b0316600d8281548110612ccc57612ccc6134df565b5f918252602090912001546001600160a01b031603612d1d5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481859191959609a1b6044820152606401610c69565b600101612ca7565b5050600d80546001810182555f919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b5f612d81612f2c565b6001600160a01b0383165f908152601060209081526040808320601190925282208154939450909290916001600160e01b039091169003612ddc5781546001600160e01b0319166ec097ce7bc90715b34b9f10000000001782555b80546001600160e01b03165f03612e0d5780546001600160e01b0319166ec097ce7bc90715b34b9f10000000001781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b805460ff166125085760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610c69565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e90612ec59030908f908f908f908f908f90600401613758565b606060405180830381865afa158015612ee0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f049190613793565b925092509250826014811115612f1c57612f1c61347b565b9b919a5098509650505050505050565b5f612f604360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612f65565b905090565b5f816401000000008410612f8c5760405162461bcd60e51b8152600401610c699190613683565b509192915050565b6001600160a01b0381168114612508575f80fd5b5f60208284031215612fb8575f80fd5b8135610c0f81612f94565b5f8060408385031215612fd4575f80fd5b8235612fdf81612f94565b91506020830135612fef81612f94565b809150509250929050565b5f805f806080858703121561300d575f80fd5b843561301881612f94565b9350602085013561302881612f94565b9250604085013561303881612f94565b9396929550929360600135925050565b5f805f6060848603121561305a575f80fd5b833561306581612f94565b9250602084013561307581612f94565b9150604084013560028110613088575f80fd5b809150509250925092565b80356001600160601b03811681146130a9575f80fd5b919050565b5f80604083850312156130bf575f80fd5b612fdf83613093565b5f602082840312156130d8575f80fd5b5035919050565b5f602082840312156130ef575f80fd5b610c0f82613093565b602080825282518282018190525f9190848201906040850190845b818110156131385783516001600160a01b031683529284019291840191600101613113565b50909695505050505050565b5f8083601f840112613154575f80fd5b50813567ffffffffffffffff81111561316b575f80fd5b6020830191508360208260051b8501011115611622575f80fd5b5f805f8060408587031215613198575f80fd5b843567ffffffffffffffff808211156131af575f80fd5b6131bb88838901613144565b909650945060208701359150808211156131d3575f80fd5b506131e087828801613144565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61322c60608301866131ec565b931515602083015250901515604090910152919050565b5f8060408385031215613254575f80fd5b823561325f81612f94565b946020939093013593505050565b5f806020838503121561327e575f80fd5b823567ffffffffffffffff811115613294575f80fd5b6132a085828601613144565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b81811015613138578351835292840192918401916001016132c7565b5f805f606084860312156132f5575f80fd5b833561330081612f94565b9250602084013561331081612f94565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215613345575f80fd5b813567ffffffffffffffff8082111561335c575f80fd5b818401915084601f83011261336f575f80fd5b81358181111561338157613381613321565b604051601f8201601f19908116603f011681019083821181831017156133a9576133a9613321565b816040528281528760208487010111156133c1575f80fd5b826020860160208301375f928101602001929092525095945050505050565b8015158114612508575f80fd5b5f80604083850312156133fe575f80fd5b823561340981612f94565b91506020830135612fef816133e0565b5f806040838503121561342a575f80fd5b823561343581612f94565b9150602083013560098110612fef575f80fd5b5f8060408385031215613459575f80fd5b823561346481612f94565b915061347260208401613093565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156134a0575f80fd5b505080516020909101519092909150565b600281106134cd57634e487b7160e01b5f52602160045260245ffd5b9052565b602081016112b582846134b1565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061350757607f821691505b60208210810361352557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b5f600182016135505761355061352b565b5060010190565b5f6001600160601b038083168181036135725761357261352b565b6001019392505050565b601f82111561245657805f5260205f20601f840160051c810160208510156135a15750805b601f840160051c820191505b818110156135c0575f81556001016135ad565b5050505050565b815167ffffffffffffffff8111156135e1576135e1613321565b6135f5816135ef84546134f3565b8461357c565b602080601f831160018114613628575f84156136115750858301515b5f19600386901b1c1916600185901b178555611486565b5f85815260208120601f198616915b8281101561365657888601518255948401946001909101908401613637565b508582101561367357878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b602081525f610c0f60208301846131ec565b818103818111156112b5576112b561352b565b634e487b7160e01b5f52603160045260245ffd5b5f805f80608085870312156136cf575f80fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613713575f80fd5b5051919050565b6001600160a01b03831681526040602082018190525f90612c62908301846131ec565b5f6020828403121561374d575f80fd5b8151610c0f816133e0565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101611f6260a08301846134b1565b5f805f606084860312156137a5575f80fd5b835192506020840151915060408401519050925092509256fe616464506f6f6c4d61726b6574732875696e7439365b5d2c616464726573735b5d29a2646970667358221220bb3741952e77e5cd5b9ed84d8dc734611bb6edf887e2b22b9cdb301cd004f8ad64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061044d575f3560e01c806396c9906411610242578063cab4f84c11610140578063e0f6123d116100bf578063f02fdf9711610084578063f02fdf9714610b48578063f445d70314610b5b578063f851a44014610b88578063f968273214610b9a578063fa6331d814610bad575f80fd5b8063e0f6123d14610ac0578063e37d4b7914610ae2578063e85a296014610b19578063e875544614610b2c578063ede4edd014610b35575f80fd5b8063d585c3c611610105578063d585c3c614610a61578063d686e9ee14610a74578063dce1544914610a87578063dcfbc0c714610a9a578063ddbf54fd14610aad575f80fd5b8063cab4f84c1461088c578063d0d1303614610a21578063d137f36e14610a34578063d3270f9914610a47578063d463654c14610a5a575f80fd5b8063b8324c7c116101cc578063c299823811610191578063c29982381461099a578063c488847b146109ba578063c5b4db55146109cd578063c5f956af146109fb578063c7ee005e14610a0e575f80fd5b8063b8324c7c146108f3578063bb82aa5e1461094e578063bbb8864a14610961578063bec04f7214610980578063bf32442d14610989575f80fd5b8063a78dc77511610212578063a78dc7751461089f578063abfceffc146108b2578063afd3783b146108c5578063b0772d0b146108d8578063b2eafc39146108e0575f80fd5b806396c99064146108445780639bb27d6214610866578063a657e57914610879578063a76b3fda1461088c575f80fd5b80634a5844321161034f5780637d172bd5116102d95780638c1ac18a1161029e5780638c1ac18a146107e05780638e8f294b146108025780639254f5e514610815578063929fe9a11461082857806394b2294b1461083b575f80fd5b80637d172bd5146107795780637dc0d1d01461078c5780637fb8e8cd1461079f57806389c13be0146107ac5780638a7dc165146107c1575f80fd5b806363e0d6341161031f57806363e0d634146106eb578063719f701b1461070b578063737690991461071457806376551383146107545780637b86e42c14610766575f80fd5b80634a584432146106875780634d99c776146106a657806352d84d1e146106b95780635dd3fc9d146106cc575f80fd5b806321af4569116103db5780633093c11e116103a05780633093c11e146105d05780633d98a1e51461062a5780634088c73e1461063d57806341a18d2c1461064a578063425fad5814610674575f80fd5b806321af45691461054d578063236175851461057857806324a3d6221461058b578063267822471461059e5780632bc7e29e146105b1575f80fd5b806308e0225c1161042157806308e0225c146104b25780630db4b4e5146104dc5780630ef332ca146104e557806310b983381461050d57806319ef3e8b1461053a575f80fd5b80627e3dd21461045157806302c3bcbb1461046957806304ef9d58146104965780630686dab61461049f575b5f80fd5b60015b60405190151581526020015b60405180910390f35b610488610477366004612fa8565b60276020525f908152604090205481565b604051908152602001610460565b61048860225481565b6104886104ad366004612fa8565b610bb6565b6104886104c0366004612fc3565b601360209081525f928352604080842090915290825290205481565b610488601d5481565b6104f86104f3366004612ffa565b61107c565b60408051928352602083019190915201610460565b61045461051b366004612fc3565b602c60209081525f928352604080842090915290825290205460ff1681565b610488610548366004613048565b611119565b601e54610560906001600160a01b031681565b6040516001600160a01b039091168152602001610460565b610488610586366004612fa8565b6111ab565b600a54610560906001600160a01b031681565b600154610560906001600160a01b031681565b6104886105bf366004612fa8565b60166020525f908152604090205481565b6105e36105de3660046130ae565b6111c1565b604080519715158852602088019690965293151594860194909452606085019190915260808401526001600160601b0390911660a0830152151560c082015260e001610460565b610454610638366004612fa8565b611286565b6018546104549060ff1681565b610488610658366004612fc3565b601260209081525f928352604080842090915290825290205481565b6018546104549062010000900460ff1681565b610488610695366004612fa8565b601f6020525f908152604090205481565b6104886106b43660046130ae565b61129a565b6105606106c73660046130c8565b6112bb565b6104886106da366004612fa8565b602b6020525f908152604090205481565b6106fe6106f93660046130df565b6112e3565b60405161046091906130f8565b610488601c5481565b61073c610722366004612fa8565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610460565b60185461045490610100900460ff1681565b610488610774366004612fa8565b6113bc565b601b54610560906001600160a01b031681565b600454610560906001600160a01b031681565b6039546104549060ff1681565b6107bf6107ba366004613185565b6113d1565b005b6104886107cf366004612fa8565b60146020525f908152604090205481565b6104546107ee366004612fa8565b602d6020525f908152604090205460ff1681565b6105e3610810366004612fa8565b61148e565b601554610560906001600160a01b031681565b610454610836366004612fc3565b6114b6565b61048860075481565b6108576108523660046130df565b6114e5565b6040516104609392919061321a565b602554610560906001600160a01b031681565b60375461073c906001600160601b031681565b61048861089a366004612fa8565b611592565b6104f86108ad366004613243565b61159c565b6106fe6108c0366004612fa8565b611629565b6104886108d3366004612fc3565b611786565b6106fe6117bd565b602054610560906001600160a01b031681565b61092a610901366004612fa8565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610460565b600254610560906001600160a01b031681565b61048861096f366004612fa8565b602a6020525f908152604090205481565b61048860175481565b6033546001600160a01b0316610560565b6109ad6109a836600461326d565b61181d565b60405161046091906132ac565b6104f86109c83660046132e3565b6118d6565b6109e36ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b039091168152602001610460565b602154610560906001600160a01b031681565b603154610560906001600160a01b031681565b61073c610a2f366004613335565b61196a565b6107bf610a423660046130ae565b611a70565b602654610560906001600160a01b031681565b61073c5f81565b610488610a6f366004612fc3565b611cca565b610488610a82366004612fa8565b611d40565b610560610a95366004613243565b611d55565b600354610560906001600160a01b031681565b6107bf610abb3660046133ed565b611d89565b610454610ace366004612fa8565b60386020525f908152604090205460ff1681565b61092a610af0366004612fa8565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b610454610b27366004613419565b611e1b565b61048860055481565b610488610b43366004612fa8565b611e5f565b610454610b56366004613448565b612108565b610454610b69366004612fc3565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610560906001600160a01b031681565b6107bf610ba83660046130df565b612297565b610488601a5481565b5f610bed60405180604001604052806015815260200174756e6c6973744d61726b657428616464726573732960581b81525061245b565b5f610bf78361250b565b805490915060ff16610c1657610c0f6009601861252d565b9392505050565b610c21836002611e1b565b610c725760405162461bcd60e51b815260206004820152601b60248201527f626f72726f7720616374696f6e206973206e6f7420706175736564000000000060448201526064015b60405180910390fd5b610c7c835f611e1b565b610cc85760405162461bcd60e51b815260206004820152601960248201527f6d696e7420616374696f6e206973206e6f7420706175736564000000000000006044820152606401610c69565b610cd3836001611e1b565b610d1f5760405162461bcd60e51b815260206004820152601b60248201527f72656465656d20616374696f6e206973206e6f742070617573656400000000006044820152606401610c69565b610d2a836003611e1b565b610d765760405162461bcd60e51b815260206004820152601a60248201527f726570617920616374696f6e206973206e6f74207061757365640000000000006044820152606401610c69565b610d81836007611e1b565b610dd75760405162461bcd60e51b815260206004820152602160248201527f656e746572206d61726b657420616374696f6e206973206e6f742070617573656044820152601960fa1b6064820152608401610c69565b610de2836005611e1b565b610e2e5760405162461bcd60e51b815260206004820152601e60248201527f6c697175696461746520616374696f6e206973206e6f742070617573656400006044820152606401610c69565b610e39836004611e1b565b610e855760405162461bcd60e51b815260206004820152601a60248201527f7365697a6520616374696f6e206973206e6f74207061757365640000000000006044820152606401610c69565b610e90836006611e1b565b610edc5760405162461bcd60e51b815260206004820152601d60248201527f7472616e7366657220616374696f6e206973206e6f74207061757365640000006044820152606401610c69565b610ee7836008611e1b565b610f335760405162461bcd60e51b815260206004820181905260248201527f65786974206d61726b657420616374696f6e206973206e6f74207061757365646044820152606401610c69565b6001600160a01b0383165f908152601f602052604090205415610f8e5760405162461bcd60e51b81526020600482015260136024820152720626f72726f7720636170206973206e6f74203606c1b6044820152606401610c69565b6001600160a01b0383165f9081526027602052604090205415610fe95760405162461bcd60e51b81526020600482015260136024820152720737570706c7920636170206973206e6f74203606c1b6044820152606401610c69565b60018101541561103b5760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206973206e6f7420300000000000006044820152606401610c69565b805460ff191681556040516001600160a01b038416907f302feb03efd5741df80efe7f97f5d93d74d46a542a3d312d0faae64fa1f3e0e9905f90a25f610c0f565b602654604051630a5d5a0560e41b81526001600160a01b03868116600483015230602483015285811660448301528481166064830152608482018490525f92839283928392169063a5d5a0509060a4016040805180830381865afa1580156110e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110a919061348f565b90999098509650505050505050565b6001600160a01b0383165f9081526035602052604081205481908190611148906001600160601b0316866125a4565b5090925090505f8460018111156111615761116161347b565b0361116e57509050610c0f565b60018460018111156111825761118261347b565b03611190579150610c0f9050565b83604051632f03799f60e11b8152600401610c6991906134d1565b5f806111b75f846125a4565b5090949350505050565b5f805f805f805f60375f9054906101000a90046001600160601b03166001600160601b0316896001600160601b0316111561121a57604051632db8671b60e11b81526001600160601b038a166004820152602401610c69565b5f6112258a8a61129a565b5f9081526009602052604090208054600182015460038301546004840154600585015460069095015460ff9485169d50929b50908316995097509195506001600160601b0382169450600160601b9091041691505092959891949750929550565b5f6112908261250b565b5460ff1692915050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d81815481106112ca575f80fd5b5f918252602090912001546001600160a01b0316905081565b6037546060906001600160601b03908116908316111561132157604051632db8671b60e11b81526001600160601b0383166004820152602401610c69565b6001600160601b03821661134857604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f90815260366020908152604091829020600101805483518184028101840190945280845290918301828280156113b057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611392575b50505050509050919050565b5f806113c85f846125a4565b50949350505050565b6113f26040518060600160405280602281526020016137bf6022913961245b565b828015806114005750808214155b1561141e5760405163512509d360e11b815260040160405180910390fd5b5f5b818110156114865761147e86868381811061143d5761143d6134df565b905060200201602081019061145291906130df565b858584818110611464576114646134df565b90506020020160208101906114799190612fa8565b612656565b600101611420565b505050505050565b5f805f805f805f61149f5f896111c1565b959e949d50929b5090995097509550909350915050565b5f6114c08261250b565b6001600160a01b03939093165f90815260029093016020525050604090205460ff1690565b60366020525f90815260409020805481906114ff906134f3565b80601f016020809104026020016040519081016040528092919081815260200182805461152b906134f3565b80156115765780601f1061154d57610100808354040283529160200191611576565b820191905f5260205f20905b81548152906001019060200180831161155957829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6112b582612839565b6026546040516304f65f8b60e21b81523060048201526001600160a01b038481166024830152604482018490525f9283928392839216906313d97e2c906064016040805180830381865afa1580156115f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061161a919061348f565b909450925050505b9250929050565b6001600160a01b0381165f908152600860209081526040808320805482518185028101850190935280835260609493849392919083018282801561169457602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611676575b505050505090505f815190505f8167ffffffffffffffff8111156116ba576116ba613321565b6040519080825280602002602001820160405280156116e3578160200160208202803683370190505b5090505f5b82811015611779575f611713858381518110611706576117066134df565b602002602001015161250b565b805490915060ff161561177057848281518110611732576117326134df565b602002602001015183878151811061174c5761174c6134df565b6001600160a01b039092166020928302919091019091015261176d8661353f565b95505b506001016116e8565b5092835250909392505050565b6001600160a01b0382165f9081526035602052604081205481906117b3906001600160601b0316846125a4565b9695505050505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561181357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116117f5575b5050505050905090565b6060815f8167ffffffffffffffff81111561183a5761183a613321565b604051908082528060200260200182016040528015611863578160200160208202803683370190505b5090505f5b828110156113c8576118a0868683818110611885576118856134df565b905060200201602081019061189a9190612fa8565b3361296d565b60148111156118b1576118b161347b565b8282815181106118c3576118c36134df565b6020908102919091010152600101611868565b602654604051630779996560e11b81523060048201526001600160a01b0385811660248301528481166044830152606482018490525f928392839283921690630ef332ca906084016040805180830381865afa158015611938573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061195c919061348f565b909890975095505050505050565b5f61199e60405180604001604052806012815260200171637265617465506f6f6c28737472696e672960701b81525061245b565b81515f036119bf5760405163522e397360e11b815260040160405180910390fd5b603780545f919082906119da906001600160601b0316613557565b82546001600160601b038083166101009490940a848102910219909116179092555f90815260366020526040902090915080611a1685826135c7565b5060028101805460ff191660011790556040516001600160601b038316907fc419386a8582a5374f4db03fdbb9fd99c73ef32d6ce9fc3a8c249e97bf31f9af90611a61908790613683565b60405180910390a25092915050565b611aae6040518060400160405280602081526020017f72656d6f7665506f6f6c4d61726b65742875696e7439362c616464726573732981525061245b565b6001600160601b038216611ad557604051630203217b60e61b815260040160405180910390fd5b5f611ae0838361129a565b5f8181526009602052604090205490915060ff16611b2b576040516338ddb96b60e11b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c69565b6001600160601b0383165f908152603660205260408120600101805490915b81811015611c3857846001600160a01b0316838281548110611b6e57611b6e6134df565b5f918252602090912001546001600160a01b031603611c305782611b93600184613695565b81548110611ba357611ba36134df565b905f5260205f20015f9054906101000a90046001600160a01b0316838281548110611bd057611bd06134df565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480611c0b57611c0b6136a8565b5f8281526020902081015f1990810180546001600160a01b0319169055019055611c38565b600101611b4a565b505f83815260096020526040808220805460ff199081168255600182018490556003820180549091169055600481018390556005810183905560060180546cffffffffffffffffffffffffff19169055516001600160a01b038616916001600160601b038816917fc8bef274db6d8c804aba68a69e64268bcfe7dd0aead2efcec0cac73a2df56e129190a35050505050565b5f336001600160a01b03841614801590611d0757506001600160a01b0383165f908152602c6020908152604080832033845290915290205460ff16155b15611d25576040516337248ad960e01b815260040160405180910390fd5b611d2f828461296d565b6014811115610c0f57610c0f61347b565b5f80611d4c5f846125a4565b95945050505050565b6008602052815f5260405f208181548110611d6e575f80fd5b5f918252602090912001546001600160a01b03169150829050565b611d9282612a40565b335f908152602c602090815260408083206001600160a01b038616845290915290205481151560ff909116151503611e0c5760405162461bcd60e51b815260206004820152601b60248201527f44656c65676174696f6e2073746174757320756e6368616e67656400000000006044820152606401610c69565b611e17338383612a8e565b5050565b6001600160a01b0382165f90815260296020526040812081836008811115611e4557611e4561347b565b815260208101919091526040015f205460ff169392505050565b5f611e6b826008612afa565b6040516361bfb47160e11b815233600482015282905f90819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa158015611eb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ed991906136bc565b50925092509250825f14611f2f5760405162461bcd60e51b815260206004820152601960248201527f6765744163636f756e74536e617073686f74206661696c6564000000000000006044820152606401610c69565b8015611f41576117b3600c600261252d565b5f611f4d873385612b44565b90508015611f6d57611f62600e600383612beb565b979650505050505050565b5f611f778661250b565b335f90815260028201602052604090205490915060ff16611f9f575f98975050505050505050565b335f9081526002820160209081526040808320805460ff1916905560089091528120805490915b818110156120b457886001600160a01b0316838281548110611fea57611fea6134df565b5f918252602090912001546001600160a01b0316036120ac578261200f600184613695565b8154811061201f5761201f6134df565b905f5260205f20015f9054906101000a90046001600160a01b031683828154811061204c5761204c6134df565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480612087576120876136a8565b5f8281526020902081015f1990810180546001600160a01b03191690550190556120b4565b600101611fc6565b8181106120c3576120c36136ef565b60405133906001600160a01b038b16907fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d905f90a35f9b9a5050505050505050505050565b6001600160a01b0382165f9081526008602090815260408083208054825181850281018501909352808352849383018282801561216c57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161214e575b50939450505050506001600160601b038316158015906121a257506001600160a01b0384165f9081526016602052604090205415155b156121b0575f9150506112b5565b5f5b815181101561228c575f8282815181106121ce576121ce6134df565b602002602001015190505f6121e3868361129a565b5f81815260096020526040902060060154909150600160601b900460ff16612282576040516395dd919360e01b81526001600160a01b0388811660048301525f91908416906395dd919390602401602060405180830381865afa15801561224c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122709190613703565b1115612282575f9450505050506112b5565b50506001016121b2565b506001949350505050565b6037546001600160601b0390811690821611156122d257604051632db8671b60e11b81526001600160601b0382166004820152602401610c69565b335f908152603560205260409020546001600160601b039081169082160361230d57604051631c9d4f3960e31b815260040160405180910390fd5b6001600160601b0381161580159061234057506001600160601b0381165f9081526036602052604090206002015460ff16155b1561236957604051632da4cc0560e01b81526001600160601b0382166004820152602401610c69565b6123733382612108565b6123905760405163592ec11d60e01b815260040160405180910390fd5b335f818152603560209081526040918290205491516001600160601b03928316815291841692917f9181876220501cdac3aa7278fd34e9bd150c30a27b6ed95458fe859761b071f7910160405180910390a3335f81815260356020526040812080546bffffffffffffffffffffffff19166001600160601b03851617905590819061241b9082612c6a565b9250509150815f14158061242e57505f81115b156124565760405163c978466160e01b81526004810183905260248101829052604401610c69565b505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab9061248d903390859060040161371a565b602060405180830381865afa1580156124a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124cc919061373d565b6125085760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610c69565b50565b5f60095f6125195f8561129a565b81526020019081526020015f209050919050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360148111156125615761256161347b565b83601a8111156125735761257361347b565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610c0f57610c0f61347b565b6001600160601b0382165f818152603660205260408120909182918291829015806125d45750600282015460ff16155b156125e9576125e28661250b565b9050612638565b5f6125f4888861129a565b5f81815260096020526040902080549192509060ff1615801561262057506002840154610100900460ff165b61262a5780612633565b6126338861250b565b925050505b80600101548160040154826005015494509450945050509250925092565b6001600160601b03821661267d57604051630203217b60e61b815260040160405180910390fd5b6037546001600160601b0390811690831611156126b857604051632db8671b60e11b81526001600160601b0383166004820152602401610c69565b6001600160601b0382165f9081526036602052604090206002015460ff166126fe57604051632da4cc0560e01b81526001600160601b0383166004820152602401610c69565b5f6127095f8361129a565b5f8181526009602052604090205490915060ff1661273a576040516386dccab760e01b815260040160405180910390fd5b612744838361129a565b5f8181526009602052604090205490915060ff16156127905760405163d9d72f2b60e01b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c69565b5f8181526009602090815260408083206006810180546bffffffffffffffffffffffff19166001600160601b038916908117909155815460ff19166001908117835581865260368552838620810180549182018155865293852090930180546001600160a01b0319166001600160a01b038816908117909155915190939192917f2159e9508e372ac69e1047a124c5478445206066e5d7df7e4214a1986cd78c8091a350505050565b5f6128786040518060400160405280601781526020017f5f737570706f72744d61726b657428616464726573732900000000000000000081525061245b565b6128818261250b565b5460ff1615612896576112b5600a601161252d565b816001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128f6919061373d565b505f6129018361250b565b8054600160ff19918216811783556003830180549092169091555f90820155905061292b83612ca2565b61293483612d78565b6040516001600160a01b038416907fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f905f90a25f610c0f565b5f612979836007612afa565b5f6129838461250b565b905061298e81612e3a565b6001600160a01b0383165f90815260028201602052604090205460ff16156129b9575f9150506112b5565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b6001600160a01b0381166125085760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610c69565b6001600160a01b038381165f818152602c6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fcb325b7784f78486e42849c7a50b8c5ee008d00cd90e108a58912c0fcb6288b4910160405180910390a3505050565b612b048282611e1b565b15611e175760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610c69565b5f612b56612b518561250b565b612e3a565b612b5f8461250b565b6001600160a01b0384165f908152600291909101602052604090205460ff16612b8957505f610c0f565b5f80612b988587865f80612e7f565b9193509091505f9050826014811115612bb357612bb361347b565b14612bd357816014811115612bca57612bca61347b565b92505050610c0f565b8015612be0576004612bca565b5f9695505050505050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846014811115612c1f57612c1f61347b565b84601a811115612c3157612c3161347b565b604080519283526020830191909152810184905260600160405180910390a1836014811115612c6257612c6261347b565b949350505050565b5f805f805f80612c7d885f805f8b612e7f565b925092509250826014811115612c9557612c9561347b565b9891975095509350505050565b600d545f5b81811015612d2557826001600160a01b0316600d8281548110612ccc57612ccc6134df565b5f918252602090912001546001600160a01b031603612d1d5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481859191959609a1b6044820152606401610c69565b600101612ca7565b5050600d80546001810182555f919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b5f612d81612f2c565b6001600160a01b0383165f908152601060209081526040808320601190925282208154939450909290916001600160e01b039091169003612ddc5781546001600160e01b0319166ec097ce7bc90715b34b9f10000000001782555b80546001600160e01b03165f03612e0d5780546001600160e01b0319166ec097ce7bc90715b34b9f10000000001781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b805460ff166125085760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610c69565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e90612ec59030908f908f908f908f908f90600401613758565b606060405180830381865afa158015612ee0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f049190613793565b925092509250826014811115612f1c57612f1c61347b565b9b919a5098509650505050505050565b5f612f604360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612f65565b905090565b5f816401000000008410612f8c5760405162461bcd60e51b8152600401610c699190613683565b509192915050565b6001600160a01b0381168114612508575f80fd5b5f60208284031215612fb8575f80fd5b8135610c0f81612f94565b5f8060408385031215612fd4575f80fd5b8235612fdf81612f94565b91506020830135612fef81612f94565b809150509250929050565b5f805f806080858703121561300d575f80fd5b843561301881612f94565b9350602085013561302881612f94565b9250604085013561303881612f94565b9396929550929360600135925050565b5f805f6060848603121561305a575f80fd5b833561306581612f94565b9250602084013561307581612f94565b9150604084013560028110613088575f80fd5b809150509250925092565b80356001600160601b03811681146130a9575f80fd5b919050565b5f80604083850312156130bf575f80fd5b612fdf83613093565b5f602082840312156130d8575f80fd5b5035919050565b5f602082840312156130ef575f80fd5b610c0f82613093565b602080825282518282018190525f9190848201906040850190845b818110156131385783516001600160a01b031683529284019291840191600101613113565b50909695505050505050565b5f8083601f840112613154575f80fd5b50813567ffffffffffffffff81111561316b575f80fd5b6020830191508360208260051b8501011115611622575f80fd5b5f805f8060408587031215613198575f80fd5b843567ffffffffffffffff808211156131af575f80fd5b6131bb88838901613144565b909650945060208701359150808211156131d3575f80fd5b506131e087828801613144565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61322c60608301866131ec565b931515602083015250901515604090910152919050565b5f8060408385031215613254575f80fd5b823561325f81612f94565b946020939093013593505050565b5f806020838503121561327e575f80fd5b823567ffffffffffffffff811115613294575f80fd5b6132a085828601613144565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b81811015613138578351835292840192918401916001016132c7565b5f805f606084860312156132f5575f80fd5b833561330081612f94565b9250602084013561331081612f94565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215613345575f80fd5b813567ffffffffffffffff8082111561335c575f80fd5b818401915084601f83011261336f575f80fd5b81358181111561338157613381613321565b604051601f8201601f19908116603f011681019083821181831017156133a9576133a9613321565b816040528281528760208487010111156133c1575f80fd5b826020860160208301375f928101602001929092525095945050505050565b8015158114612508575f80fd5b5f80604083850312156133fe575f80fd5b823561340981612f94565b91506020830135612fef816133e0565b5f806040838503121561342a575f80fd5b823561343581612f94565b9150602083013560098110612fef575f80fd5b5f8060408385031215613459575f80fd5b823561346481612f94565b915061347260208401613093565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156134a0575f80fd5b505080516020909101519092909150565b600281106134cd57634e487b7160e01b5f52602160045260245ffd5b9052565b602081016112b582846134b1565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061350757607f821691505b60208210810361352557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b5f600182016135505761355061352b565b5060010190565b5f6001600160601b038083168181036135725761357261352b565b6001019392505050565b601f82111561245657805f5260205f20601f840160051c810160208510156135a15750805b601f840160051c820191505b818110156135c0575f81556001016135ad565b5050505050565b815167ffffffffffffffff8111156135e1576135e1613321565b6135f5816135ef84546134f3565b8461357c565b602080601f831160018114613628575f84156136115750858301515b5f19600386901b1c1916600185901b178555611486565b5f85815260208120601f198616915b8281101561365657888601518255948401946001909101908401613637565b508582101561367357878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b602081525f610c0f60208301846131ec565b818103818111156112b5576112b561352b565b634e487b7160e01b5f52603160045260245ffd5b5f805f80608085870312156136cf575f80fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613713575f80fd5b5051919050565b6001600160a01b03831681526040602082018190525f90612c62908301846131ec565b5f6020828403121561374d575f80fd5b8151610c0f816133e0565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101611f6260a08301846134b1565b5f805f606084860312156137a5575f80fd5b835192506020840151915060408401519050925092509256fe616464506f6f6c4d61726b6574732875696e7439365b5d2c616464726573735b5d29a2646970667358221220bb3741952e77e5cd5b9ed84d8dc734611bb6edf887e2b22b9cdb301cd004f8ad64736f6c63430008190033", + "numDeployments": 2, + "solcInputHash": "cbc4287e135101fe4c78448d0f5f2ecc", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"DelegateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketUnlisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"PoolCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"PoolMarketInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"previousPoolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"newPoolId\",\"type\":\"uint96\"}],\"name\":\"PoolSelected\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96[]\",\"name\":\"poolIds\",\"type\":\"uint96[]\"},{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"addPoolMarkets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"createPool\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"enterMarketBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"enterPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getEffectiveLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"enum WeightFunction\",\"name\":\"weightingStrategy\",\"type\":\"uint8\"}],\"name\":\"getEffectiveLtvFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getLiquidationThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"getPoolVTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"targetPoolId\",\"type\":\"uint96\"}],\"name\":\"hasValidPoolBorrows\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"isMarketListed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateVAICalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isVenus\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"marketPoolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"isBorrowAllowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"poolMarkets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isVenus\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"marketPoolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"isBorrowAllowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"removePoolMarket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"unlistMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"updateDelegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the methods related to the market's management in the pool\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_supportMarket(address)\":{\"details\":\"Allows a privileged role to add and list markets to the Comptroller\",\"params\":{\"vToken\":\"The address of the vToken market to list in the Core Pool\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"addPoolMarkets(uint96[],address[])\":{\"custom:error\":\"ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.MarketNotListedInCorePool Reverts if the market is not listed in the core pool.MarketAlreadyListed Reverts if the given market is already listed in the specified pool.InactivePool Reverts if attempted to add markets to an inactive pool.\",\"custom:event\":\"PoolMarketInitialized Emitted after successfully initializing a market in a pool.\",\"params\":{\"poolIds\":\"Array of pool IDs.\",\"vTokens\":\"Array of market (vToken) addresses.\"}},\"checkMembership(address,address)\":{\"details\":\"Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools, all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\",\"params\":{\"account\":\"The address of the account to check\",\"vToken\":\"The vToken to check\"},\"returns\":{\"_0\":\"True if the account is in the asset, otherwise false\"}},\"createPool(string)\":{\"custom:error\":\"EmptyPoolLabel Reverts if the provided label is an empty string.\",\"custom:event\":\"PoolCreated Emitted after successfully creating a new pool.\",\"params\":{\"label\":\"name for the pool (must be non-empty).\"},\"returns\":{\"_0\":\"poolId The incremental unique identifier of the newly created pool.\"}},\"enterMarketBehalf(address,address)\":{\"custom:error\":\"NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\",\"details\":\"Only callable by the account itself or an approved delegate\",\"params\":{\"onBehalf\":\"The address of the account entering the market\",\"vToken\":\"The address of the vToken market to enable for the account\"},\"returns\":{\"_0\":\"uint256 indicating the result (0 = success, non-zero = failure)\"}},\"enterMarkets(address[])\":{\"params\":{\"vTokens\":\"The list of addresses of the vToken markets to be enabled\"},\"returns\":{\"_0\":\"Success indicator for whether each corresponding market was entered\"}},\"enterPool(uint96)\":{\"custom:error\":\"PoolDoesNotExist The specified pool ID does not exist.AlreadyInSelectedPool The user is already in the target pool.IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.LiquidityCheckFailed The user's liquidity is insufficient after switching pools.InactivePool The user is trying to enter inactive pool.\",\"custom:event\":\"PoolSelected Emitted after a successful pool switch.\",\"params\":{\"poolId\":\"The ID of the pool the user wants to enter.\"}},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow\",\"params\":{\"vTokenAddress\":\"The address of the asset to be removed\"},\"returns\":{\"_0\":\"Whether or not the account successfully exited the market\"}},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market\",\"returns\":{\"_0\":\"The list of market addresses\"}},\"getAssetsIn(address)\":{\"details\":\"Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools, all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\",\"params\":{\"account\":\"The address of the account to query\"},\"returns\":{\"_0\":\"assets A dynamic array of vToken markets the account has entered\"}},\"getCollateralFactor(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the collateral factor for\"},\"returns\":{\"_0\":\"The collateral factor for the vToken, scaled by 1e18\"}},\"getEffectiveLiquidationIncentive(address,address)\":{\"details\":\"The incentive is determined by the pool entered by the account and the specified vToken via `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\",\"params\":{\"account\":\"The account whose pool is used to determine the market's risk parameters\",\"vToken\":\"The address of the vToken market\"},\"returns\":{\"_0\":\"The liquidation Incentive for the vToken, scaled by 1e18\"}},\"getEffectiveLtvFactor(address,address,uint8)\":{\"details\":\"The value is determined by the pool entered by the account and the specified vToken via `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used. This value is used for account liquidity calculations and liquidation checks.\",\"params\":{\"account\":\"The account whose pool is used to determine the market's risk parameters.\",\"vToken\":\"The address of the vToken market.\",\"weightingStrategy\":\"The weighting strategy to use: - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\"},\"returns\":{\"_0\":\"factor The effective loan-to-value factor, scaled by 1e18.\"}},\"getLiquidationIncentive(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the liquidation Incentive for\"},\"returns\":{\"_0\":\"liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\"}},\"getLiquidationThreshold(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the liquidation threshold for\"},\"returns\":{\"_0\":\"The liquidation threshold for the vToken, scaled by 1e18\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getPoolVTokens(uint96)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the given pool ID do not exist.InvalidOperationForCorePool Reverts if called on the Core Pool.\",\"params\":{\"poolId\":\"The ID of the pool whose vTokens are being queried.\"},\"returns\":{\"_0\":\"An array of vToken addresses associated with the pool.\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"hasValidPoolBorrows(address,uint96)\":{\"params\":{\"account\":\"The address of the user attempting to switch pools.\",\"targetPoolId\":\"The pool ID the user wants to switch into.\"},\"returns\":{\"_0\":\"bool True if the switch is allowed, otherwise False.\"}},\"isMarketListed(address)\":{\"params\":{\"vToken\":\"The vToken Address of the market to check\"},\"returns\":{\"_0\":\"listed True if the (Core Pool, vToken) market is listed, otherwise false\"}},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"borrower\":\"Address of borrower whose collateral is being seized\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"liquidateVAICalculateSeizeTokens(address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"markets(address)\":{\"details\":\"Fetches the Market struct associated with the core pool and returns all relevant parameters.\",\"params\":{\"vToken\":\"The address of the vToken whose market configuration is to be fetched.\"},\"returns\":{\"collateralFactorMantissa\":\"The maximum borrowable percentage of collateral, in mantissa.\",\"isBorrowAllowed\":\"Whether borrowing is allowed in this market.\",\"isListed\":\"Whether the market is listed and enabled.\",\"isVenus\":\"Whether this market is eligible for VENUS rewards.\",\"liquidationIncentiveMantissa\":\"The max liquidation incentive allowed for this market, in mantissa.\",\"liquidationThresholdMantissa\":\"The threshold at which liquidation is triggered, in mantissa.\",\"marketPoolId\":\"The pool ID this market belongs to.\"}},\"poolMarkets(uint96,address)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the given pool ID do not exist.\",\"details\":\"Fetches the Market struct associated with the poolId and returns all relevant parameters.\",\"params\":{\"poolId\":\"The ID of the pool whose market configuration is being queried.\",\"vToken\":\"The address of the vToken whose market configuration is to be fetched.\"},\"returns\":{\"collateralFactorMantissa\":\"The maximum borrowable percentage of collateral, in mantissa.\",\"isBorrowAllowed\":\"Whether borrowing is allowed in this market.\",\"isListed\":\"Whether the market is listed and enabled.\",\"isVenus\":\"Whether this market is eligible for XVS rewards.\",\"liquidationIncentiveMantissa\":\"The liquidation incentive allowed for this market, in mantissa.\",\"liquidationThresholdMantissa\":\"The threshold at which liquidation is triggered, in mantissa.\",\"marketPoolId\":\"The pool ID this market belongs to.\"}},\"removePoolMarket(uint96,address)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts if called on the Core Pool.PoolMarketNotFound Reverts if the market is not listed in the pool.\",\"custom:event\":\"PoolMarketRemoved Emitted after a market is successfully removed from a pool.\",\"params\":{\"poolId\":\"The ID of the pool from which the market should be removed.\",\"vToken\":\"The address of the market token to remove.\"}},\"supportMarket(address)\":{\"params\":{\"vToken\":\"The address of the market (token) to list\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"unlistMarket(address)\":{\"details\":\"Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\",\"params\":{\"market\":\"The address of the market (vToken) to unlist\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (See enum Error for details)\"}},\"updateDelegate(address,bool)\":{\"params\":{\"approved\":\"Whether to grant (true) or revoke (false) the borrowing or redeeming rights\",\"delegate\":\"The address to update the rights for\"}}},\"title\":\"MarketFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DelegateUpdated(address,address,bool)\":{\"notice\":\"Emitted when the borrowing or redeeming delegate rights are updated for an account\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"MarketExited(address,address)\":{\"notice\":\"Emitted when an account exits a market\"},\"MarketListed(address)\":{\"notice\":\"Emitted when an admin supports a market\"},\"MarketUnlisted(address)\":{\"notice\":\"Emitted when an admin unlists a market\"},\"PoolCreated(uint96,string)\":{\"notice\":\"Emitted when a new pool is created\"},\"PoolMarketInitialized(uint96,address)\":{\"notice\":\"Emitted when a market is initialized in a pool\"},\"PoolMarketRemoved(uint96,address)\":{\"notice\":\"Emitted when a vToken market is removed from a pool\"},\"PoolSelected(address,uint96,uint96)\":{\"notice\":\"Emitted when a user enters or exits a pool (poolId = 0 means exit)\"}},\"kind\":\"user\",\"methods\":{\"_supportMarket(address)\":{\"notice\":\"Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"addPoolMarkets(uint96[],address[])\":{\"notice\":\"Batch initializes market entries with basic config.\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account has entered the specified vToken market in the Core Pool\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"createPool(string)\":{\"notice\":\"Creates a new pool with the given label.\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"enterMarketBehalf(address,address)\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"enterPool(uint96)\":{\"notice\":\"Allows a user to switch to a new pool (e.g., e-mode ).\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the vToken markets an account has entered in the Core Pool\"},\"getCollateralFactor(address)\":{\"notice\":\"Get the core pool collateral factor for a vToken\"},\"getEffectiveLiquidationIncentive(address,address)\":{\"notice\":\"Get the Effective Liquidation Incentive for a given account and market\"},\"getEffectiveLtvFactor(address,address,uint8)\":{\"notice\":\"Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\"},\"getLiquidationIncentive(address)\":{\"notice\":\"Get the core pool liquidation Incentive for a vToken\"},\"getLiquidationThreshold(address)\":{\"notice\":\"Get the core pool liquidation threshold for a vToken\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getPoolVTokens(uint96)\":{\"notice\":\"Returns the full list of vTokens for a given pool ID.\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"hasValidPoolBorrows(address,uint96)\":{\"notice\":\"Returns true if the user can switch to the given target pool, i.e., all markets they have borrowed from are also borrowable in the target pool.\"},\"isComptroller()\":{\"notice\":\"Indicator that this is a Comptroller contract (for inspection)\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"isMarketListed(address)\":{\"notice\":\"Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidateVAICalculateSeizeTokens(address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"markets(address)\":{\"notice\":\"Returns the market configuration for a vToken in the core pool (poolId = 0).\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"poolMarkets(uint96,address)\":{\"notice\":\"Returns the market configuration for a vToken from _poolMarkets.\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"removePoolMarket(uint96,address)\":{\"notice\":\"Removes a market (vToken) from the specified pool.\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"supportMarket(address)\":{\"notice\":\"Alias to _supportMarket to support the Isolated Lending Comptroller Interface\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"unlistMarket(address)\":{\"notice\":\"Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\"},\"updateDelegate(address,bool)\":{\"notice\":\"Grants or revokes the borrowing or redeeming delegate rights to / from an account If allowed, the delegate will be able to borrow funds on behalf of the sender Upon a delegated borrow, the delegate will receive the funds, and the borrower will see the debt on their account Upon a delegated redeem, the delegate will receive the redeemed amount and the approver will see a deduction in his vToken balance\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains functions regarding markets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/MarketFacet.sol\":\"MarketFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\\n enum KeeperAction {\\n SetMinPrice,\\n SetMaxPrice,\\n ExitProtectionMode\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool cachingEnabled;\\n }\\n\\n /// @notice One item in an syncPriceBoundsAndProtections payload\\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\\n struct KeeperActionItem {\\n address asset;\\n KeeperAction action;\\n uint256 value;\\n }\\n\\n /// @notice One item in a setTokenConfigs payload\\n struct TokenConfigInput {\\n /// @notice The underlying asset address\\n address asset;\\n /// @notice Minimum time protection stays active after the last trigger (seconds)\\n uint64 cooldownPeriod;\\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\\n uint256 triggerThreshold;\\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\\n uint256 resetThreshold;\\n /// @notice Whether to enable bounded pricing immediately upon initialization\\n bool enableBoundedPricing;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool enableCaching;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n /// @notice Emitted when the per-asset transient caching flag is toggled\\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\\n error InvalidKeeperAction(uint8 action);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage. The transient\\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n /**\\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\\n * Empty `actions` is a no-op success.\\n * @param actions The list of keeper actions to apply\\n * @custom:access Only authorized keeper addresses\\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\\n */\\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param tokenConfig_ Token config input for the asset\\n * @custom:access Only Governance\\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param tokenConfigs_ Array of token config inputs, one per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if the input array is empty\\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\\n * @custom:error VAINotAllowed if any asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n /**\\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\\n * live spot instead of reading or writing the transient slots. The initial value is\\n * set via the `enableCaching` argument of `setTokenConfig`.\\n * @param asset The underlying asset address\\n * @param enabled Whether transient caching is enabled for this asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CachingEnabledUpdated\\n */\\n function setCachingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold,\\n bool cachingEnabled\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0xe223d88c17c0d752fdb33fa223b63ce124a798512f3d69f3800e9508e7dff931\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/MarketFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IMarketFacet } from \\\"../interfaces/IMarketFacet.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title MarketFacet\\n * @author Venus\\n * @dev This facet contains all the methods related to the market's management in the pool\\n * @notice This facet contract contains functions regarding markets\\n */\\ncontract MarketFacet is IMarketFacet, FacetBase {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(VToken indexed vToken);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account\\n event DelegateUpdated(address indexed approver, address indexed delegate, bool approved);\\n\\n /// @notice Emitted when an admin unlists a market\\n event MarketUnlisted(address indexed vToken);\\n\\n /// @notice Emitted when a market is initialized in a pool\\n event PoolMarketInitialized(uint96 indexed poolId, address indexed market);\\n\\n /// @notice Emitted when a user enters or exits a pool (poolId = 0 means exit)\\n event PoolSelected(address indexed account, uint96 previousPoolId, uint96 indexed newPoolId);\\n\\n /// @notice Emitted when a vToken market is removed from a pool\\n event PoolMarketRemoved(uint96 indexed poolId, address indexed vToken);\\n\\n /// @notice Emitted when a new pool is created\\n event PoolCreated(uint96 indexed poolId, string label);\\n\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() public pure returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Returns the vToken markets an account has entered in the Core Pool\\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\\n * @param account The address of the account to query\\n * @return assets A dynamic array of vToken markets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n uint256 len;\\n VToken[] memory _accountAssets = accountAssets[account];\\n uint256 _accountAssetsLength = _accountAssets.length;\\n\\n VToken[] memory assetsIn = new VToken[](_accountAssetsLength);\\n\\n for (uint256 i; i < _accountAssetsLength; ++i) {\\n Market storage market = getCorePoolMarket(address(_accountAssets[i]));\\n if (market.isListed) {\\n assetsIn[len] = _accountAssets[i];\\n ++len;\\n }\\n }\\n\\n assembly {\\n mstore(assetsIn, len)\\n }\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market\\n * @return The list of market addresses\\n */\\n function getAllMarkets() external view returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\\n address(this),\\n vTokenBorrowed,\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param borrower Address of borrower whose collateral is being seized\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n vTokenBorrowed,\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\\n address(this),\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns whether the given account has entered the specified vToken market in the Core Pool\\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the asset, otherwise false\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return getCorePoolMarket(address(vToken)).accountMembership[account];\\n }\\n\\n /**\\n * @notice Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken Address of the market to check\\n * @return listed True if the (Core Pool, vToken) market is listed, otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return getCorePoolMarket(address(vToken)).isListed;\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @dev Only callable by the account itself or an approved delegate\\n * @param onBehalf The address of the account entering the market\\n * @param vToken The address of the vToken market to enable for the account\\n * @return uint256 indicating the result (0 = success, non-zero = failure)\\n * @custom:error NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\\n */\\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256) {\\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\\n revert NotAnApprovedDelegate();\\n }\\n return uint256(addToMarketInternal(VToken(vToken), onBehalf));\\n }\\n\\n /**\\n * @notice Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\\n * @dev Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\\n * @param market The address of the market (vToken) to unlist\\n * @return uint256 0=success, otherwise a failure (See enum Error for details)\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n ensureAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = getCorePoolMarket(market);\\n\\n if (!_market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.UNLIST_MARKET_NOT_LISTED);\\n }\\n\\n require(actionPaused(market, Action.BORROW), \\\"borrow action is not paused\\\");\\n require(actionPaused(market, Action.MINT), \\\"mint action is not paused\\\");\\n require(actionPaused(market, Action.REDEEM), \\\"redeem action is not paused\\\");\\n require(actionPaused(market, Action.REPAY), \\\"repay action is not paused\\\");\\n require(actionPaused(market, Action.ENTER_MARKET), \\\"enter market action is not paused\\\");\\n require(actionPaused(market, Action.LIQUIDATE), \\\"liquidate action is not paused\\\");\\n require(actionPaused(market, Action.SEIZE), \\\"seize action is not paused\\\");\\n require(actionPaused(market, Action.TRANSFER), \\\"transfer action is not paused\\\");\\n require(actionPaused(market, Action.EXIT_MARKET), \\\"exit market action is not paused\\\");\\n\\n require(borrowCaps[market] == 0, \\\"borrow cap is not 0\\\");\\n require(supplyCaps[market] == 0, \\\"supply cap is not 0\\\");\\n\\n require(_market.collateralFactorMantissa == 0, \\\"collateral factor is not 0\\\");\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow\\n * @param vTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address vTokenAddress) external returns (uint256) {\\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = getCorePoolMarket(address(vToken));\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n uint256 i;\\n for (; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n userAssetList[i] = userAssetList[len - 1];\\n userAssetList.pop();\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(i < len);\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Alias to _supportMarket to support the Isolated Lending Comptroller Interface\\n * @param vToken The address of the market (token) to list\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function supportMarket(VToken vToken) external returns (uint256) {\\n return __supportMarket(vToken);\\n }\\n\\n /**\\n * @notice Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\\n * @dev Allows a privileged role to add and list markets to the Comptroller\\n * @param vToken The address of the vToken market to list in the Core Pool\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(VToken vToken) external returns (uint256) {\\n return __supportMarket(vToken);\\n }\\n\\n /**\\n * @notice Grants or revokes the borrowing or redeeming delegate rights to / from an account\\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\\n * will see the debt on their account\\n * Upon a delegated redeem, the delegate will receive the redeemed amount and the approver\\n * will see a deduction in his vToken balance\\n * @param delegate The address to update the rights for\\n * @param approved Whether to grant (true) or revoke (false) the borrowing or redeeming rights\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n require(approvedDelegates[msg.sender][delegate] != approved, \\\"Delegation status unchanged\\\");\\n\\n _updateDelegate(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Allows a user to switch to a new pool (e.g., e-mode ).\\n * @param poolId The ID of the pool the user wants to enter.\\n * @custom:error PoolDoesNotExist The specified pool ID does not exist.\\n * @custom:error AlreadyInSelectedPool The user is already in the target pool.\\n * @custom:error IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.\\n * @custom:error LiquidityCheckFailed The user's liquidity is insufficient after switching pools.\\n * @custom:error InactivePool The user is trying to enter inactive pool.\\n * @custom:event PoolSelected Emitted after a successful pool switch.\\n */\\n function enterPool(uint96 poolId) external {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n if (poolId == userPoolId[msg.sender]) {\\n revert AlreadyInSelectedPool();\\n }\\n\\n if (poolId != corePoolId && !pools[poolId].isActive) {\\n revert InactivePool(poolId);\\n }\\n\\n if (!hasValidPoolBorrows(msg.sender, poolId)) {\\n revert IncompatibleBorrowedAssets();\\n }\\n\\n emit PoolSelected(msg.sender, userPoolId[msg.sender], poolId);\\n\\n userPoolId[msg.sender] = poolId;\\n\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n msg.sender,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR || shortfall > 0) {\\n revert LiquidityCheckFailed(uint256(err), shortfall);\\n }\\n }\\n\\n /**\\n * @notice Creates a new pool with the given label.\\n * @param label name for the pool (must be non-empty).\\n * @return poolId The incremental unique identifier of the newly created pool.\\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string.\\n * @custom:event PoolCreated Emitted after successfully creating a new pool.\\n */\\n function createPool(string memory label) external returns (uint96) {\\n ensureAllowed(\\\"createPool(string)\\\");\\n\\n if (bytes(label).length == 0) {\\n revert EmptyPoolLabel();\\n }\\n\\n uint96 poolId = ++lastPoolId;\\n PoolData storage newPool = pools[poolId];\\n newPool.label = label;\\n newPool.isActive = true;\\n\\n emit PoolCreated(poolId, label);\\n return poolId;\\n }\\n\\n /**\\n * @notice Batch initializes market entries with basic config.\\n * @param poolIds Array of pool IDs.\\n * @param vTokens Array of market (vToken) addresses.\\n * @custom:error ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:error MarketNotListedInCorePool Reverts if the market is not listed in the core pool.\\n * @custom:error MarketAlreadyListed Reverts if the given market is already listed in the specified pool.\\n * @custom:error InactivePool Reverts if attempted to add markets to an inactive pool.\\n * @custom:event PoolMarketInitialized Emitted after successfully initializing a market in a pool.\\n */\\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external {\\n ensureAllowed(\\\"addPoolMarkets(uint96[],address[])\\\");\\n\\n uint256 len = poolIds.length;\\n if (len == 0 || len != vTokens.length) {\\n revert ArrayLengthMismatch();\\n }\\n\\n for (uint256 i; i < len; i++) {\\n _addPoolMarket(poolIds[i], vTokens[i]);\\n }\\n }\\n\\n /**\\n * @notice Removes a market (vToken) from the specified pool.\\n * @param poolId The ID of the pool from which the market should be removed.\\n * @param vToken The address of the market token to remove.\\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\\n * @custom:error PoolMarketNotFound Reverts if the market is not listed in the pool.\\n * @custom:event PoolMarketRemoved Emitted after a market is successfully removed from a pool.\\n */\\n function removePoolMarket(uint96 poolId, address vToken) external {\\n ensureAllowed(\\\"removePoolMarket(uint96,address)\\\");\\n\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\\n if (!_poolMarkets[index].isListed) {\\n revert PoolMarketNotFound(poolId, vToken);\\n }\\n\\n address[] storage assets = pools[poolId].vTokens;\\n\\n uint256 length = assets.length;\\n for (uint256 i; i < length; i++) {\\n if (assets[i] == vToken) {\\n assets[i] = assets[length - 1];\\n assets.pop();\\n break;\\n }\\n }\\n\\n delete _poolMarkets[index];\\n\\n emit PoolMarketRemoved(poolId, vToken);\\n }\\n\\n /**\\n * @notice Get the core pool collateral factor for a vToken\\n * @param vToken The address of the vToken to get the collateral factor for\\n * @return The collateral factor for the vToken, scaled by 1e18\\n */\\n function getCollateralFactor(address vToken) external view returns (uint256) {\\n (uint256 cf, , ) = getLiquidationParams(corePoolId, vToken);\\n return cf;\\n }\\n\\n /**\\n * @notice Get the core pool liquidation threshold for a vToken\\n * @param vToken The address of the vToken to get the liquidation threshold for\\n * @return The liquidation threshold for the vToken, scaled by 1e18\\n */\\n function getLiquidationThreshold(address vToken) external view returns (uint256) {\\n (, uint256 lt, ) = getLiquidationParams(corePoolId, vToken);\\n return lt;\\n }\\n\\n /**\\n * @notice Get the core pool liquidation Incentive for a vToken\\n * @param vToken The address of the vToken to get the liquidation Incentive for\\n * @return liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\\n */\\n function getLiquidationIncentive(address vToken) external view returns (uint256) {\\n (, , uint256 li) = getLiquidationParams(corePoolId, vToken);\\n return li;\\n }\\n\\n /**\\n * @notice Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\\n * @dev The value is determined by the pool entered by the account and the specified vToken via\\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used.\\n * This value is used for account liquidity calculations and liquidation checks.\\n * @param account The account whose pool is used to determine the market's risk parameters.\\n * @param vToken The address of the vToken market.\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return factor The effective loan-to-value factor, scaled by 1e18.\\n */\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256) {\\n (uint256 cf, uint256 lt, ) = getLiquidationParams(userPoolId[account], vToken);\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) return cf;\\n else if (weightingStrategy == WeightFunction.USE_LIQUIDATION_THRESHOLD) return lt;\\n else revert InvalidWeightingStrategy(weightingStrategy);\\n }\\n\\n /**\\n * @notice Get the Effective Liquidation Incentive for a given account and market\\n * @dev The incentive is determined by the pool entered by the account and the specified vToken via\\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\\n * @param account The account whose pool is used to determine the market's risk parameters\\n * @param vToken The address of the vToken market\\n * @return The liquidation Incentive for the vToken, scaled by 1e18\\n */\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256) {\\n (, , uint256 li) = getLiquidationParams(userPoolId[account], vToken);\\n return li;\\n }\\n\\n /**\\n * @notice Returns the full list of vTokens for a given pool ID.\\n * @param poolId The ID of the pool whose vTokens are being queried.\\n * @return An array of vToken addresses associated with the pool.\\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\\n */\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory) {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n return pools[poolId].vTokens;\\n }\\n\\n /**\\n * @notice Returns the market configuration for a vToken in the core pool (poolId = 0).\\n * @dev Fetches the Market struct associated with the core pool and returns all relevant parameters.\\n * @param vToken The address of the vToken whose market configuration is to be fetched.\\n * @return isListed Whether the market is listed and enabled.\\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\\n * @return isVenus Whether this market is eligible for VENUS rewards.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The max liquidation incentive allowed for this market, in mantissa.\\n * @return marketPoolId The pool ID this market belongs to.\\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\\n */\\n function markets(\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n )\\n {\\n return poolMarkets(corePoolId, vToken);\\n }\\n\\n /**\\n * @notice Returns the market configuration for a vToken from _poolMarkets.\\n * @dev Fetches the Market struct associated with the poolId and returns all relevant parameters.\\n * @param poolId The ID of the pool whose market configuration is being queried.\\n * @param vToken The address of the vToken whose market configuration is to be fetched.\\n * @return isListed Whether the market is listed and enabled.\\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\\n * @return isVenus Whether this market is eligible for XVS rewards.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\\n * @return marketPoolId The pool ID this market belongs to.\\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\\n */\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n public\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n )\\n {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n PoolMarketId key = getPoolMarketIndex(poolId, vToken);\\n Market storage m = _poolMarkets[key];\\n\\n return (\\n m.isListed,\\n m.collateralFactorMantissa,\\n m.isVenus,\\n m.liquidationThresholdMantissa,\\n m.liquidationIncentiveMantissa,\\n m.poolId,\\n m.isBorrowAllowed\\n );\\n }\\n\\n /**\\n * @notice Returns true if the user can switch to the given target pool, i.e.,\\n * all markets they have borrowed from are also borrowable in the target pool.\\n * @param account The address of the user attempting to switch pools.\\n * @param targetPoolId The pool ID the user wants to switch into.\\n * @return bool True if the switch is allowed, otherwise False.\\n */\\n function hasValidPoolBorrows(address account, uint96 targetPoolId) public view returns (bool) {\\n VToken[] memory assets = accountAssets[account];\\n if (targetPoolId != corePoolId && mintedVAIs[account] > 0) {\\n return false;\\n }\\n\\n for (uint256 i; i < assets.length; i++) {\\n VToken vToken = assets[i];\\n PoolMarketId index = getPoolMarketIndex(targetPoolId, address(vToken));\\n\\n if (!_poolMarkets[index].isBorrowAllowed) {\\n if (vToken.borrowBalanceStored(account) > 0) {\\n return false;\\n }\\n }\\n }\\n return true;\\n }\\n\\n function _updateDelegate(address approver, address delegate, bool approved) internal {\\n approvedDelegates[approver][delegate] = approved;\\n emit DelegateUpdated(approver, delegate, approved);\\n }\\n\\n function _addMarketInternal(VToken vToken) internal {\\n uint256 allMarketsLength = allMarkets.length;\\n for (uint256 i; i < allMarketsLength; ++i) {\\n require(allMarkets[i] != vToken, \\\"already added\\\");\\n }\\n allMarkets.push(vToken);\\n }\\n\\n function _initializeMarket(address vToken) internal {\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = venusInitialIndex;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = venusInitialIndex;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n function __supportMarket(VToken vToken) internal returns (uint256) {\\n ensureAllowed(\\\"_supportMarket(address)\\\");\\n\\n if (getCorePoolMarket(address(vToken)).isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n vToken.isVToken(); // Sanity check to make sure its really a VToken\\n\\n // Note that isVenus is not in active use anymore\\n Market storage newMarket = getCorePoolMarket(address(vToken));\\n newMarket.isListed = true;\\n newMarket.isVenus = false;\\n newMarket.collateralFactorMantissa = 0;\\n\\n _addMarketInternal(vToken);\\n _initializeMarket(address(vToken));\\n\\n emit MarketListed(vToken);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n function _addPoolMarket(uint96 poolId, address vToken) internal {\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (!pools[poolId].isActive) revert InactivePool(poolId);\\n\\n // Core Pool Index\\n PoolMarketId index = getPoolMarketIndex(corePoolId, vToken);\\n if (!_poolMarkets[index].isListed) revert MarketNotListedInCorePool();\\n\\n // Pool Index\\n index = getPoolMarketIndex(poolId, vToken);\\n if (_poolMarkets[index].isListed) revert MarketAlreadyListed(poolId, vToken);\\n\\n Market storage m = _poolMarkets[index];\\n m.poolId = poolId;\\n m.isListed = true;\\n\\n pools[poolId].vTokens.push(vToken);\\n\\n emit PoolMarketInitialized(poolId, vToken);\\n }\\n\\n /**\\n * @notice Returns only the core risk parameters (CF, LI, LT) for a vToken in a specific pool.\\n * @dev If the pool is inactive, or if the vToken is not configured in the given pool and\\n * `allowCorePoolFallback` is enabled, falls back to the core pool (poolId = 0) values.\\n * @return collateralFactorMantissa The max borrowable percentage of collateral, in mantissa.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\\n */\\n function getLiquidationParams(\\n uint96 poolId,\\n address vToken\\n )\\n internal\\n view\\n returns (\\n uint256 collateralFactorMantissa,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa\\n )\\n {\\n PoolData storage pool = pools[poolId];\\n Market storage market;\\n\\n if (poolId == corePoolId || !pool.isActive) {\\n market = getCorePoolMarket(vToken);\\n } else {\\n PoolMarketId poolKey = getPoolMarketIndex(poolId, vToken);\\n Market storage poolMarket = _poolMarkets[poolKey];\\n market = (!poolMarket.isListed && pool.allowCorePoolFallback) ? getCorePoolMarket(vToken) : poolMarket;\\n }\\n\\n return (\\n market.collateralFactorMantissa,\\n market.liquidationThresholdMantissa,\\n market.liquidationIncentiveMantissa\\n );\\n }\\n}\\n\",\"keccak256\":\"0xaf0b4e25119fcc08d66e241032cea7ea6284771bfa5588e57dc9a50bbe689a32\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IMarketFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./IFacetBase.sol\\\";\\n\\ninterface IMarketFacet {\\n function isComptroller() external pure returns (bool);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function checkMembership(address account, VToken vToken) external view returns (bool);\\n\\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256);\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n function _supportMarket(VToken vToken) external returns (uint256);\\n\\n function supportMarket(VToken vToken) external returns (uint256);\\n\\n function isMarketListed(VToken vToken) external view returns (bool);\\n\\n function getAssetsIn(address account) external view returns (VToken[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function updateDelegate(address delegate, bool allowBorrows) external;\\n\\n function unlistMarket(address market) external returns (uint256);\\n\\n function createPool(string memory label) external returns (uint96);\\n\\n function enterPool(uint96 poolId) external;\\n\\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external;\\n\\n function removePoolMarket(uint96 poolId, address vToken) external;\\n\\n function markets(\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function hasValidPoolBorrows(address user, uint96 targetPoolId) external view returns (bool);\\n\\n function getCollateralFactor(address vToken) external view returns (uint256);\\n\\n function getLiquidationThreshold(address vToken) external view returns (uint256);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x11118e9ea5b6c8df34d55ae85f4310ef9f6a7590b3a2202fbc7a2bb0b8572699\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b5061395e8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610458575f3560e01c80639bb27d6211610242578063d0d1303611610140578063e0f6123d116100bf578063f02fdf9711610084578063f02fdf9714610b6b578063f445d70314610b7e578063f851a44014610bab578063f968273214610bbd578063fa6331d814610bd0575f80fd5b8063e0f6123d14610ae3578063e37d4b7914610b05578063e85a296014610b3c578063e875544614610b4f578063ede4edd014610b58575f80fd5b8063d686e9ee11610105578063d686e9ee14610a7f578063d7c46d2d14610a92578063dce1544914610aaa578063dcfbc0c714610abd578063ddbf54fd14610ad0575f80fd5b8063d0d1303614610a2c578063d137f36e14610a3f578063d3270f9914610a52578063d463654c14610a65578063d585c3c614610a6c575f80fd5b8063bb82aa5e116101cc578063c488847b11610191578063c488847b146109c5578063c5b4db55146109d8578063c5f956af14610a06578063c7ee005e14610a19578063cab4f84c14610897575f80fd5b8063bb82aa5e14610959578063bbb8864a1461096c578063bec04f721461098b578063bf32442d14610994578063c2998238146109a5575f80fd5b8063abfceffc11610212578063abfceffc146108bd578063afd3783b146108d0578063b0772d0b146108e3578063b2eafc39146108eb578063b8324c7c146108fe575f80fd5b80639bb27d6214610871578063a657e57914610884578063a76b3fda14610897578063a78dc775146108aa575f80fd5b80634a5844321161035a5780637dc0d1d0116102d95780638e8f294b1161029e5780638e8f294b1461080d5780639254f5e514610820578063929fe9a11461083357806394b2294b1461084657806396c990641461084f575f80fd5b80637dc0d1d0146107975780637fb8e8cd146107aa57806389c13be0146107b75780638a7dc165146107cc5780638c1ac18a146107eb575f80fd5b8063719f701b1161031f578063719f701b14610716578063737690991461071f578063765513831461075f5780637b86e42c146107715780637d172bd514610784575f80fd5b80634a584432146106925780634d99c776146106b157806352d84d1e146106c45780635dd3fc9d146106d757806363e0d634146106f6575f80fd5b806321af4569116103e65780633093c11e116103ab5780633093c11e146105db5780633d98a1e5146106355780634088c73e1461064857806341a18d2c14610655578063425fad581461067f575f80fd5b806321af456914610558578063236175851461058357806324a3d6221461059657806326782247146105a95780632bc7e29e146105bc575f80fd5b806308e0225c1161042c57806308e0225c146104bd5780630db4b4e5146104e75780630ef332ca146104f057806310b983381461051857806319ef3e8b14610545575f80fd5b80627e3dd21461045c57806302c3bcbb1461047457806304ef9d58146104a15780630686dab6146104aa575b5f80fd5b60015b60405190151581526020015b60405180910390f35b6104936104823660046130f7565b60276020525f908152604090205481565b60405190815260200161046b565b61049360225481565b6104936104b83660046130f7565b610bd9565b6104936104cb366004613112565b601360209081525f928352604080842090915290825290205481565b610493601d5481565b6105036104fe366004613149565b61109f565b6040805192835260208301919091520161046b565b61045f610526366004613112565b602c60209081525f928352604080842090915290825290205460ff1681565b610493610553366004613197565b61113c565b601e5461056b906001600160a01b031681565b6040516001600160a01b03909116815260200161046b565b6104936105913660046130f7565b6111ce565b600a5461056b906001600160a01b031681565b60015461056b906001600160a01b031681565b6104936105ca3660046130f7565b60166020525f908152604090205481565b6105ee6105e93660046131fd565b6111e4565b604080519715158852602088019690965293151594860194909452606085019190915260808401526001600160601b0390911660a0830152151560c082015260e00161046b565b61045f6106433660046130f7565b6112a9565b60185461045f9060ff1681565b610493610663366004613112565b601260209081525f928352604080842090915290825290205481565b60185461045f9062010000900460ff1681565b6104936106a03660046130f7565b601f6020525f908152604090205481565b6104936106bf3660046131fd565b6112bd565b61056b6106d2366004613217565b6112de565b6104936106e53660046130f7565b602b6020525f908152604090205481565b61070961070436600461322e565b611306565b60405161046b9190613247565b610493601c5481565b61074761072d3660046130f7565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161046b565b60185461045f90610100900460ff1681565b61049361077f3660046130f7565b6113df565b601b5461056b906001600160a01b031681565b60045461056b906001600160a01b031681565b60395461045f9060ff1681565b6107ca6107c53660046132d4565b6113f4565b005b6104936107da3660046130f7565b60146020525f908152604090205481565b61045f6107f93660046130f7565b602d6020525f908152604090205460ff1681565b6105ee61081b3660046130f7565b6114b1565b60155461056b906001600160a01b031681565b61045f610841366004613112565b6114d9565b61049360075481565b61086261085d36600461322e565b611508565b60405161046b93929190613369565b60255461056b906001600160a01b031681565b603754610747906001600160601b031681565b6104936108a53660046130f7565b6115b5565b6105036108b8366004613392565b6115bf565b6107096108cb3660046130f7565b61164c565b6104936108de366004613112565b6117a9565b6107096117e0565b60205461056b906001600160a01b031681565b61093561090c3660046130f7565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161046b565b60025461056b906001600160a01b031681565b61049361097a3660046130f7565b602a6020525f908152604090205481565b61049360175481565b6033546001600160a01b031661056b565b6109b86109b33660046133bc565b611840565b60405161046b91906133fb565b6105036109d3366004613432565b6118f9565b6109ee6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b03909116815260200161046b565b60215461056b906001600160a01b031681565b60315461056b906001600160a01b031681565b610747610a3a366004613484565b61198d565b6107ca610a4d3660046131fd565b611a93565b60265461056b906001600160a01b031681565b6107475f81565b610493610a7a366004613112565b611ced565b610493610a8d3660046130f7565b611d63565b60395461056b9061010090046001600160a01b031681565b61056b610ab8366004613392565b611d78565b60035461056b906001600160a01b031681565b6107ca610ade36600461353c565b611dac565b61045f610af13660046130f7565b60386020525f908152604090205460ff1681565b610935610b133660046130f7565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61045f610b4a366004613568565b611e3e565b61049360055481565b610493610b663660046130f7565b611e82565b61045f610b79366004613597565b61212b565b61045f610b8c366004613112565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461056b906001600160a01b031681565b6107ca610bcb36600461322e565b6122ba565b610493601a5481565b5f610c1060405180604001604052806015815260200174756e6c6973744d61726b657428616464726573732960581b8152506124a8565b5f610c1a83612558565b805490915060ff16610c3957610c326009601861257a565b9392505050565b610c44836002611e3e565b610c955760405162461bcd60e51b815260206004820152601b60248201527f626f72726f7720616374696f6e206973206e6f7420706175736564000000000060448201526064015b60405180910390fd5b610c9f835f611e3e565b610ceb5760405162461bcd60e51b815260206004820152601960248201527f6d696e7420616374696f6e206973206e6f7420706175736564000000000000006044820152606401610c8c565b610cf6836001611e3e565b610d425760405162461bcd60e51b815260206004820152601b60248201527f72656465656d20616374696f6e206973206e6f742070617573656400000000006044820152606401610c8c565b610d4d836003611e3e565b610d995760405162461bcd60e51b815260206004820152601a60248201527f726570617920616374696f6e206973206e6f74207061757365640000000000006044820152606401610c8c565b610da4836007611e3e565b610dfa5760405162461bcd60e51b815260206004820152602160248201527f656e746572206d61726b657420616374696f6e206973206e6f742070617573656044820152601960fa1b6064820152608401610c8c565b610e05836005611e3e565b610e515760405162461bcd60e51b815260206004820152601e60248201527f6c697175696461746520616374696f6e206973206e6f742070617573656400006044820152606401610c8c565b610e5c836004611e3e565b610ea85760405162461bcd60e51b815260206004820152601a60248201527f7365697a6520616374696f6e206973206e6f74207061757365640000000000006044820152606401610c8c565b610eb3836006611e3e565b610eff5760405162461bcd60e51b815260206004820152601d60248201527f7472616e7366657220616374696f6e206973206e6f74207061757365640000006044820152606401610c8c565b610f0a836008611e3e565b610f565760405162461bcd60e51b815260206004820181905260248201527f65786974206d61726b657420616374696f6e206973206e6f74207061757365646044820152606401610c8c565b6001600160a01b0383165f908152601f602052604090205415610fb15760405162461bcd60e51b81526020600482015260136024820152720626f72726f7720636170206973206e6f74203606c1b6044820152606401610c8c565b6001600160a01b0383165f908152602760205260409020541561100c5760405162461bcd60e51b81526020600482015260136024820152720737570706c7920636170206973206e6f74203606c1b6044820152606401610c8c565b60018101541561105e5760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206973206e6f7420300000000000006044820152606401610c8c565b805460ff191681556040516001600160a01b038416907f302feb03efd5741df80efe7f97f5d93d74d46a542a3d312d0faae64fa1f3e0e9905f90a25f610c32565b602654604051630a5d5a0560e41b81526001600160a01b03868116600483015230602483015285811660448301528481166064830152608482018490525f92839283928392169063a5d5a0509060a4016040805180830381865afa158015611109573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112d91906135de565b90999098509650505050505050565b6001600160a01b0383165f908152603560205260408120548190819061116b906001600160601b0316866125f1565b5090925090505f846001811115611184576111846135ca565b0361119157509050610c32565b60018460018111156111a5576111a56135ca565b036111b3579150610c329050565b83604051632f03799f60e11b8152600401610c8c9190613620565b5f806111da5f846125f1565b5090949350505050565b5f805f805f805f60375f9054906101000a90046001600160601b03166001600160601b0316896001600160601b0316111561123d57604051632db8671b60e11b81526001600160601b038a166004820152602401610c8c565b5f6112488a8a6112bd565b5f9081526009602052604090208054600182015460038301546004840154600585015460069095015460ff9485169d50929b50908316995097509195506001600160601b0382169450600160601b9091041691505092959891949750929550565b5f6112b382612558565b5460ff1692915050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d81815481106112ed575f80fd5b5f918252602090912001546001600160a01b0316905081565b6037546060906001600160601b03908116908316111561134457604051632db8671b60e11b81526001600160601b0383166004820152602401610c8c565b6001600160601b03821661136b57604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f90815260366020908152604091829020600101805483518184028101840190945280845290918301828280156113d357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116113b5575b50505050509050919050565b5f806113eb5f846125f1565b50949350505050565b611415604051806060016040528060228152602001613907602291396124a8565b828015806114235750808214155b156114415760405163512509d360e11b815260040160405180910390fd5b5f5b818110156114a9576114a18686838181106114605761146061362e565b9050602002016020810190611475919061322e565b8585848181106114875761148761362e565b905060200201602081019061149c91906130f7565b6126a3565b600101611443565b505050505050565b5f805f805f805f6114c25f896111e4565b959e949d50929b5090995097509550909350915050565b5f6114e382612558565b6001600160a01b03939093165f90815260029093016020525050604090205460ff1690565b60366020525f908152604090208054819061152290613642565b80601f016020809104026020016040519081016040528092919081815260200182805461154e90613642565b80156115995780601f1061157057610100808354040283529160200191611599565b820191905f5260205f20905b81548152906001019060200180831161157c57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6112d882612886565b6026546040516304f65f8b60e21b81523060048201526001600160a01b038481166024830152604482018490525f9283928392839216906313d97e2c906064016040805180830381865afa158015611619573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061163d91906135de565b909450925050505b9250929050565b6001600160a01b0381165f90815260086020908152604080832080548251818502810185019093528083526060949384939291908301828280156116b757602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611699575b505050505090505f815190505f8167ffffffffffffffff8111156116dd576116dd613470565b604051908082528060200260200182016040528015611706578160200160208202803683370190505b5090505f5b8281101561179c575f6117368583815181106117295761172961362e565b6020026020010151612558565b805490915060ff1615611793578482815181106117555761175561362e565b602002602001015183878151811061176f5761176f61362e565b6001600160a01b03909216602092830291909101909101526117908661368e565b95505b5060010161170b565b5092835250909392505050565b6001600160a01b0382165f9081526035602052604081205481906117d6906001600160601b0316846125f1565b9695505050505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561183657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611818575b5050505050905090565b6060815f8167ffffffffffffffff81111561185d5761185d613470565b604051908082528060200260200182016040528015611886578160200160208202803683370190505b5090505f5b828110156113eb576118c38686838181106118a8576118a861362e565b90506020020160208101906118bd91906130f7565b336129ba565b60148111156118d4576118d46135ca565b8282815181106118e6576118e661362e565b602090810291909101015260010161188b565b602654604051630779996560e11b81523060048201526001600160a01b0385811660248301528481166044830152606482018490525f928392839283921690630ef332ca906084016040805180830381865afa15801561195b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197f91906135de565b909890975095505050505050565b5f6119c160405180604001604052806012815260200171637265617465506f6f6c28737472696e672960701b8152506124a8565b81515f036119e25760405163522e397360e11b815260040160405180910390fd5b603780545f919082906119fd906001600160601b03166136a6565b82546001600160601b038083166101009490940a848102910219909116179092555f90815260366020526040902090915080611a39858261370f565b5060028101805460ff191660011790556040516001600160601b038316907fc419386a8582a5374f4db03fdbb9fd99c73ef32d6ce9fc3a8c249e97bf31f9af90611a849087906137cb565b60405180910390a25092915050565b611ad16040518060400160405280602081526020017f72656d6f7665506f6f6c4d61726b65742875696e7439362c61646472657373298152506124a8565b6001600160601b038216611af857604051630203217b60e61b815260040160405180910390fd5b5f611b0383836112bd565b5f8181526009602052604090205490915060ff16611b4e576040516338ddb96b60e11b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c8c565b6001600160601b0383165f908152603660205260408120600101805490915b81811015611c5b57846001600160a01b0316838281548110611b9157611b9161362e565b5f918252602090912001546001600160a01b031603611c535782611bb66001846137dd565b81548110611bc657611bc661362e565b905f5260205f20015f9054906101000a90046001600160a01b0316838281548110611bf357611bf361362e565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480611c2e57611c2e6137f0565b5f8281526020902081015f1990810180546001600160a01b0319169055019055611c5b565b600101611b6d565b505f83815260096020526040808220805460ff199081168255600182018490556003820180549091169055600481018390556005810183905560060180546cffffffffffffffffffffffffff19169055516001600160a01b038616916001600160601b038816917fc8bef274db6d8c804aba68a69e64268bcfe7dd0aead2efcec0cac73a2df56e129190a35050505050565b5f336001600160a01b03841614801590611d2a57506001600160a01b0383165f908152602c6020908152604080832033845290915290205460ff16155b15611d48576040516337248ad960e01b815260040160405180910390fd5b611d5282846129ba565b6014811115610c3257610c326135ca565b5f80611d6f5f846125f1565b95945050505050565b6008602052815f5260405f208181548110611d91575f80fd5b5f918252602090912001546001600160a01b03169150829050565b611db582612a8d565b335f908152602c602090815260408083206001600160a01b038616845290915290205481151560ff909116151503611e2f5760405162461bcd60e51b815260206004820152601b60248201527f44656c65676174696f6e2073746174757320756e6368616e67656400000000006044820152606401610c8c565b611e3a338383612adb565b5050565b6001600160a01b0382165f90815260296020526040812081836008811115611e6857611e686135ca565b815260208101919091526040015f205460ff169392505050565b5f611e8e826008612b47565b6040516361bfb47160e11b815233600482015282905f90819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa158015611ed8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611efc9190613804565b50925092509250825f14611f525760405162461bcd60e51b815260206004820152601960248201527f6765744163636f756e74536e617073686f74206661696c6564000000000000006044820152606401610c8c565b8015611f64576117d6600c600261257a565b5f611f70873385612b91565b90508015611f9057611f85600e600383612c38565b979650505050505050565b5f611f9a86612558565b335f90815260028201602052604090205490915060ff16611fc2575f98975050505050505050565b335f9081526002820160209081526040808320805460ff1916905560089091528120805490915b818110156120d757886001600160a01b031683828154811061200d5761200d61362e565b5f918252602090912001546001600160a01b0316036120cf57826120326001846137dd565b815481106120425761204261362e565b905f5260205f20015f9054906101000a90046001600160a01b031683828154811061206f5761206f61362e565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550828054806120aa576120aa6137f0565b5f8281526020902081015f1990810180546001600160a01b03191690550190556120d7565b600101611fe9565b8181106120e6576120e6613837565b60405133906001600160a01b038b16907fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d905f90a35f9b9a5050505050505050505050565b6001600160a01b0382165f9081526008602090815260408083208054825181850281018501909352808352849383018282801561218f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612171575b50939450505050506001600160601b038316158015906121c557506001600160a01b0384165f9081526016602052604090205415155b156121d3575f9150506112d8565b5f5b81518110156122af575f8282815181106121f1576121f161362e565b602002602001015190505f61220686836112bd565b5f81815260096020526040902060060154909150600160601b900460ff166122a5576040516395dd919360e01b81526001600160a01b0388811660048301525f91908416906395dd919390602401602060405180830381865afa15801561226f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612293919061384b565b11156122a5575f9450505050506112d8565b50506001016121d5565b506001949350505050565b6037546001600160601b0390811690821611156122f557604051632db8671b60e11b81526001600160601b0382166004820152602401610c8c565b335f908152603560205260409020546001600160601b039081169082160361233057604051631c9d4f3960e31b815260040160405180910390fd5b6001600160601b0381161580159061236357506001600160601b0381165f9081526036602052604090206002015460ff16155b1561238c57604051632da4cc0560e01b81526001600160601b0382166004820152602401610c8c565b612396338261212b565b6123b35760405163592ec11d60e01b815260040160405180910390fd5b335f818152603560209081526040918290205491516001600160601b03928316815291841692917f9181876220501cdac3aa7278fd34e9bd150c30a27b6ed95458fe859761b071f7910160405180910390a3335f81815260356020526040812080546bffffffffffffffffffffffff19166001600160601b0385161790559081906124419082808080612cb7565b9193509091505f905082601481111561245c5761245c6135ca565b14158061246857505f81115b156124a35781601481111561247f5761247f6135ca565b60405163c978466160e01b8152600481019190915260248101829052604401610c8c565b505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906124da9033908590600401613862565b602060405180830381865afa1580156124f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125199190613885565b6125555760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610c8c565b50565b5f60095f6125665f856112bd565b81526020019081526020015f209050919050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360148111156125ae576125ae6135ca565b83601a8111156125c0576125c06135ca565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610c3257610c326135ca565b6001600160601b0382165f818152603660205260408120909182918291829015806126215750600282015460ff16155b156126365761262f86612558565b9050612685565b5f61264188886112bd565b5f81815260096020526040902080549192509060ff1615801561266d57506002840154610100900460ff165b6126775780612680565b61268088612558565b925050505b80600101548160040154826005015494509450945050509250925092565b6001600160601b0382166126ca57604051630203217b60e61b815260040160405180910390fd5b6037546001600160601b03908116908316111561270557604051632db8671b60e11b81526001600160601b0383166004820152602401610c8c565b6001600160601b0382165f9081526036602052604090206002015460ff1661274b57604051632da4cc0560e01b81526001600160601b0383166004820152602401610c8c565b5f6127565f836112bd565b5f8181526009602052604090205490915060ff16612787576040516386dccab760e01b815260040160405180910390fd5b61279183836112bd565b5f8181526009602052604090205490915060ff16156127dd5760405163d9d72f2b60e01b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c8c565b5f8181526009602090815260408083206006810180546bffffffffffffffffffffffff19166001600160601b038916908117909155815460ff19166001908117835581865260368552838620810180549182018155865293852090930180546001600160a01b0319166001600160a01b038816908117909155915190939192917f2159e9508e372ac69e1047a124c5478445206066e5d7df7e4214a1986cd78c8091a350505050565b5f6128c56040518060400160405280601781526020017f5f737570706f72744d61726b65742861646472657373290000000000000000008152506124a8565b6128ce82612558565b5460ff16156128e3576112d8600a601161257a565b816001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561291f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129439190613885565b505f61294e83612558565b8054600160ff19918216811783556003830180549092169091555f90820155905061297883612d80565b61298183612e56565b6040516001600160a01b038416907fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f905f90a25f610c32565b5f6129c6836007612b47565b5f6129d084612558565b90506129db81612f18565b6001600160a01b0383165f90815260028201602052604090205460ff1615612a06575f9150506112d8565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b6001600160a01b0381166125555760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610c8c565b6001600160a01b038381165f818152602c6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fcb325b7784f78486e42849c7a50b8c5ee008d00cd90e108a58912c0fcb6288b4910160405180910390a3505050565b612b518282611e3e565b15611e3a5760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610c8c565b5f612ba3612b9e85612558565b612f18565b612bac84612558565b6001600160a01b0384165f908152600291909101602052604090205460ff16612bd657505f610c32565b5f80612be58587865f80612cb7565b9193509091505f9050826014811115612c0057612c006135ca565b14612c2057816014811115612c1757612c176135ca565b92505050610c32565b8015612c2d576004612c17565b5f9695505050505050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846014811115612c6c57612c6c6135ca565b84601a811115612c7e57612c7e6135ca565b604080519283526020830191909152810184905260600160405180910390a1836014811115612caf57612caf6135ca565b949350505050565b5f808080846001811115612ccd57612ccd6135ca565b03612cdb57612cdb88612f5d565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e90612d199030908f908f908f908f908f906004016138a0565b606060405180830381865afa158015612d34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d5891906138db565b925092509250826014811115612d7057612d706135ca565b9b919a5098509650505050505050565b600d545f5b81811015612e0357826001600160a01b0316600d8281548110612daa57612daa61362e565b5f918252602090912001546001600160a01b031603612dfb5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481859191959609a1b6044820152606401610c8c565b600101612d85565b5050600d80546001810182555f919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b5f612e5f61307b565b6001600160a01b0383165f908152601060209081526040808320601190925282208154939450909290916001600160e01b039091169003612eba5781546001600160e01b0319166ec097ce7bc90715b34b9f10000000001782555b80546001600160e01b03165f03612eeb5780546001600160e01b0319166ec097ce7bc90715b34b9f10000000001781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b805460ff166125555760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610c8c565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015612fd357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612fb5575b505083519394505f925050505b8181101561307457836001600160a01b031663a9c3cab18483815181106130095761300961362e565b60200260200101516040518263ffffffff1660e01b815260040161303c91906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015613053575f80fd5b505af1158015613065573d5f803e3d5ffd5b50505050806001019050612fe0565b5050505050565b5f6130af4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b8152506130b4565b905090565b5f8164010000000084106130db5760405162461bcd60e51b8152600401610c8c91906137cb565b509192915050565b6001600160a01b0381168114612555575f80fd5b5f60208284031215613107575f80fd5b8135610c32816130e3565b5f8060408385031215613123575f80fd5b823561312e816130e3565b9150602083013561313e816130e3565b809150509250929050565b5f805f806080858703121561315c575f80fd5b8435613167816130e3565b93506020850135613177816130e3565b92506040850135613187816130e3565b9396929550929360600135925050565b5f805f606084860312156131a9575f80fd5b83356131b4816130e3565b925060208401356131c4816130e3565b91506040840135600281106131d7575f80fd5b809150509250925092565b80356001600160601b03811681146131f8575f80fd5b919050565b5f806040838503121561320e575f80fd5b61312e836131e2565b5f60208284031215613227575f80fd5b5035919050565b5f6020828403121561323e575f80fd5b610c32826131e2565b602080825282518282018190525f9190848201906040850190845b818110156132875783516001600160a01b031683529284019291840191600101613262565b50909695505050505050565b5f8083601f8401126132a3575f80fd5b50813567ffffffffffffffff8111156132ba575f80fd5b6020830191508360208260051b8501011115611645575f80fd5b5f805f80604085870312156132e7575f80fd5b843567ffffffffffffffff808211156132fe575f80fd5b61330a88838901613293565b90965094506020870135915080821115613322575f80fd5b5061332f87828801613293565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61337b606083018661333b565b931515602083015250901515604090910152919050565b5f80604083850312156133a3575f80fd5b82356133ae816130e3565b946020939093013593505050565b5f80602083850312156133cd575f80fd5b823567ffffffffffffffff8111156133e3575f80fd5b6133ef85828601613293565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b8181101561328757835183529284019291840191600101613416565b5f805f60608486031215613444575f80fd5b833561344f816130e3565b9250602084013561345f816130e3565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215613494575f80fd5b813567ffffffffffffffff808211156134ab575f80fd5b818401915084601f8301126134be575f80fd5b8135818111156134d0576134d0613470565b604051601f8201601f19908116603f011681019083821181831017156134f8576134f8613470565b81604052828152876020848701011115613510575f80fd5b826020860160208301375f928101602001929092525095945050505050565b8015158114612555575f80fd5b5f806040838503121561354d575f80fd5b8235613558816130e3565b9150602083013561313e8161352f565b5f8060408385031215613579575f80fd5b8235613584816130e3565b915060208301356009811061313e575f80fd5b5f80604083850312156135a8575f80fd5b82356135b3816130e3565b91506135c1602084016131e2565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156135ef575f80fd5b505080516020909101519092909150565b6002811061361c57634e487b7160e01b5f52602160045260245ffd5b9052565b602081016112d88284613600565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061365657607f821691505b60208210810361367457634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161369f5761369f61367a565b5060010190565b5f6001600160601b038083168181036136c1576136c161367a565b6001019392505050565b601f8211156124a357805f5260205f20601f840160051c810160208510156136f05750805b601f840160051c820191505b81811015613074575f81556001016136fc565b815167ffffffffffffffff81111561372957613729613470565b61373d816137378454613642565b846136cb565b602080601f831160018114613770575f84156137595750858301515b5f19600386901b1c1916600185901b1785556114a9565b5f85815260208120601f198616915b8281101561379e5788860151825594840194600190910190840161377f565b50858210156137bb57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b602081525f610c32602083018461333b565b818103818111156112d8576112d861367a565b634e487b7160e01b5f52603160045260245ffd5b5f805f8060808587031215613817575f80fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b5f52600160045260245ffd5b5f6020828403121561385b575f80fd5b5051919050565b6001600160a01b03831681526040602082018190525f90612caf9083018461333b565b5f60208284031215613895575f80fd5b8151610c328161352f565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101611f8560a0830184613600565b5f805f606084860312156138ed575f80fd5b835192506020840151915060408401519050925092509256fe616464506f6f6c4d61726b6574732875696e7439365b5d2c616464726573735b5d29a26469706673582212203504412fc390ce3c0a3481ff369b4e1708c86eb2a968acc7786b35dd85f2e44364736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610458575f3560e01c80639bb27d6211610242578063d0d1303611610140578063e0f6123d116100bf578063f02fdf9711610084578063f02fdf9714610b6b578063f445d70314610b7e578063f851a44014610bab578063f968273214610bbd578063fa6331d814610bd0575f80fd5b8063e0f6123d14610ae3578063e37d4b7914610b05578063e85a296014610b3c578063e875544614610b4f578063ede4edd014610b58575f80fd5b8063d686e9ee11610105578063d686e9ee14610a7f578063d7c46d2d14610a92578063dce1544914610aaa578063dcfbc0c714610abd578063ddbf54fd14610ad0575f80fd5b8063d0d1303614610a2c578063d137f36e14610a3f578063d3270f9914610a52578063d463654c14610a65578063d585c3c614610a6c575f80fd5b8063bb82aa5e116101cc578063c488847b11610191578063c488847b146109c5578063c5b4db55146109d8578063c5f956af14610a06578063c7ee005e14610a19578063cab4f84c14610897575f80fd5b8063bb82aa5e14610959578063bbb8864a1461096c578063bec04f721461098b578063bf32442d14610994578063c2998238146109a5575f80fd5b8063abfceffc11610212578063abfceffc146108bd578063afd3783b146108d0578063b0772d0b146108e3578063b2eafc39146108eb578063b8324c7c146108fe575f80fd5b80639bb27d6214610871578063a657e57914610884578063a76b3fda14610897578063a78dc775146108aa575f80fd5b80634a5844321161035a5780637dc0d1d0116102d95780638e8f294b1161029e5780638e8f294b1461080d5780639254f5e514610820578063929fe9a11461083357806394b2294b1461084657806396c990641461084f575f80fd5b80637dc0d1d0146107975780637fb8e8cd146107aa57806389c13be0146107b75780638a7dc165146107cc5780638c1ac18a146107eb575f80fd5b8063719f701b1161031f578063719f701b14610716578063737690991461071f578063765513831461075f5780637b86e42c146107715780637d172bd514610784575f80fd5b80634a584432146106925780634d99c776146106b157806352d84d1e146106c45780635dd3fc9d146106d757806363e0d634146106f6575f80fd5b806321af4569116103e65780633093c11e116103ab5780633093c11e146105db5780633d98a1e5146106355780634088c73e1461064857806341a18d2c14610655578063425fad581461067f575f80fd5b806321af456914610558578063236175851461058357806324a3d6221461059657806326782247146105a95780632bc7e29e146105bc575f80fd5b806308e0225c1161042c57806308e0225c146104bd5780630db4b4e5146104e75780630ef332ca146104f057806310b983381461051857806319ef3e8b14610545575f80fd5b80627e3dd21461045c57806302c3bcbb1461047457806304ef9d58146104a15780630686dab6146104aa575b5f80fd5b60015b60405190151581526020015b60405180910390f35b6104936104823660046130f7565b60276020525f908152604090205481565b60405190815260200161046b565b61049360225481565b6104936104b83660046130f7565b610bd9565b6104936104cb366004613112565b601360209081525f928352604080842090915290825290205481565b610493601d5481565b6105036104fe366004613149565b61109f565b6040805192835260208301919091520161046b565b61045f610526366004613112565b602c60209081525f928352604080842090915290825290205460ff1681565b610493610553366004613197565b61113c565b601e5461056b906001600160a01b031681565b6040516001600160a01b03909116815260200161046b565b6104936105913660046130f7565b6111ce565b600a5461056b906001600160a01b031681565b60015461056b906001600160a01b031681565b6104936105ca3660046130f7565b60166020525f908152604090205481565b6105ee6105e93660046131fd565b6111e4565b604080519715158852602088019690965293151594860194909452606085019190915260808401526001600160601b0390911660a0830152151560c082015260e00161046b565b61045f6106433660046130f7565b6112a9565b60185461045f9060ff1681565b610493610663366004613112565b601260209081525f928352604080842090915290825290205481565b60185461045f9062010000900460ff1681565b6104936106a03660046130f7565b601f6020525f908152604090205481565b6104936106bf3660046131fd565b6112bd565b61056b6106d2366004613217565b6112de565b6104936106e53660046130f7565b602b6020525f908152604090205481565b61070961070436600461322e565b611306565b60405161046b9190613247565b610493601c5481565b61074761072d3660046130f7565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161046b565b60185461045f90610100900460ff1681565b61049361077f3660046130f7565b6113df565b601b5461056b906001600160a01b031681565b60045461056b906001600160a01b031681565b60395461045f9060ff1681565b6107ca6107c53660046132d4565b6113f4565b005b6104936107da3660046130f7565b60146020525f908152604090205481565b61045f6107f93660046130f7565b602d6020525f908152604090205460ff1681565b6105ee61081b3660046130f7565b6114b1565b60155461056b906001600160a01b031681565b61045f610841366004613112565b6114d9565b61049360075481565b61086261085d36600461322e565b611508565b60405161046b93929190613369565b60255461056b906001600160a01b031681565b603754610747906001600160601b031681565b6104936108a53660046130f7565b6115b5565b6105036108b8366004613392565b6115bf565b6107096108cb3660046130f7565b61164c565b6104936108de366004613112565b6117a9565b6107096117e0565b60205461056b906001600160a01b031681565b61093561090c3660046130f7565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161046b565b60025461056b906001600160a01b031681565b61049361097a3660046130f7565b602a6020525f908152604090205481565b61049360175481565b6033546001600160a01b031661056b565b6109b86109b33660046133bc565b611840565b60405161046b91906133fb565b6105036109d3366004613432565b6118f9565b6109ee6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b03909116815260200161046b565b60215461056b906001600160a01b031681565b60315461056b906001600160a01b031681565b610747610a3a366004613484565b61198d565b6107ca610a4d3660046131fd565b611a93565b60265461056b906001600160a01b031681565b6107475f81565b610493610a7a366004613112565b611ced565b610493610a8d3660046130f7565b611d63565b60395461056b9061010090046001600160a01b031681565b61056b610ab8366004613392565b611d78565b60035461056b906001600160a01b031681565b6107ca610ade36600461353c565b611dac565b61045f610af13660046130f7565b60386020525f908152604090205460ff1681565b610935610b133660046130f7565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61045f610b4a366004613568565b611e3e565b61049360055481565b610493610b663660046130f7565b611e82565b61045f610b79366004613597565b61212b565b61045f610b8c366004613112565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461056b906001600160a01b031681565b6107ca610bcb36600461322e565b6122ba565b610493601a5481565b5f610c1060405180604001604052806015815260200174756e6c6973744d61726b657428616464726573732960581b8152506124a8565b5f610c1a83612558565b805490915060ff16610c3957610c326009601861257a565b9392505050565b610c44836002611e3e565b610c955760405162461bcd60e51b815260206004820152601b60248201527f626f72726f7720616374696f6e206973206e6f7420706175736564000000000060448201526064015b60405180910390fd5b610c9f835f611e3e565b610ceb5760405162461bcd60e51b815260206004820152601960248201527f6d696e7420616374696f6e206973206e6f7420706175736564000000000000006044820152606401610c8c565b610cf6836001611e3e565b610d425760405162461bcd60e51b815260206004820152601b60248201527f72656465656d20616374696f6e206973206e6f742070617573656400000000006044820152606401610c8c565b610d4d836003611e3e565b610d995760405162461bcd60e51b815260206004820152601a60248201527f726570617920616374696f6e206973206e6f74207061757365640000000000006044820152606401610c8c565b610da4836007611e3e565b610dfa5760405162461bcd60e51b815260206004820152602160248201527f656e746572206d61726b657420616374696f6e206973206e6f742070617573656044820152601960fa1b6064820152608401610c8c565b610e05836005611e3e565b610e515760405162461bcd60e51b815260206004820152601e60248201527f6c697175696461746520616374696f6e206973206e6f742070617573656400006044820152606401610c8c565b610e5c836004611e3e565b610ea85760405162461bcd60e51b815260206004820152601a60248201527f7365697a6520616374696f6e206973206e6f74207061757365640000000000006044820152606401610c8c565b610eb3836006611e3e565b610eff5760405162461bcd60e51b815260206004820152601d60248201527f7472616e7366657220616374696f6e206973206e6f74207061757365640000006044820152606401610c8c565b610f0a836008611e3e565b610f565760405162461bcd60e51b815260206004820181905260248201527f65786974206d61726b657420616374696f6e206973206e6f74207061757365646044820152606401610c8c565b6001600160a01b0383165f908152601f602052604090205415610fb15760405162461bcd60e51b81526020600482015260136024820152720626f72726f7720636170206973206e6f74203606c1b6044820152606401610c8c565b6001600160a01b0383165f908152602760205260409020541561100c5760405162461bcd60e51b81526020600482015260136024820152720737570706c7920636170206973206e6f74203606c1b6044820152606401610c8c565b60018101541561105e5760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206973206e6f7420300000000000006044820152606401610c8c565b805460ff191681556040516001600160a01b038416907f302feb03efd5741df80efe7f97f5d93d74d46a542a3d312d0faae64fa1f3e0e9905f90a25f610c32565b602654604051630a5d5a0560e41b81526001600160a01b03868116600483015230602483015285811660448301528481166064830152608482018490525f92839283928392169063a5d5a0509060a4016040805180830381865afa158015611109573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112d91906135de565b90999098509650505050505050565b6001600160a01b0383165f908152603560205260408120548190819061116b906001600160601b0316866125f1565b5090925090505f846001811115611184576111846135ca565b0361119157509050610c32565b60018460018111156111a5576111a56135ca565b036111b3579150610c329050565b83604051632f03799f60e11b8152600401610c8c9190613620565b5f806111da5f846125f1565b5090949350505050565b5f805f805f805f60375f9054906101000a90046001600160601b03166001600160601b0316896001600160601b0316111561123d57604051632db8671b60e11b81526001600160601b038a166004820152602401610c8c565b5f6112488a8a6112bd565b5f9081526009602052604090208054600182015460038301546004840154600585015460069095015460ff9485169d50929b50908316995097509195506001600160601b0382169450600160601b9091041691505092959891949750929550565b5f6112b382612558565b5460ff1692915050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d81815481106112ed575f80fd5b5f918252602090912001546001600160a01b0316905081565b6037546060906001600160601b03908116908316111561134457604051632db8671b60e11b81526001600160601b0383166004820152602401610c8c565b6001600160601b03821661136b57604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f90815260366020908152604091829020600101805483518184028101840190945280845290918301828280156113d357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116113b5575b50505050509050919050565b5f806113eb5f846125f1565b50949350505050565b611415604051806060016040528060228152602001613907602291396124a8565b828015806114235750808214155b156114415760405163512509d360e11b815260040160405180910390fd5b5f5b818110156114a9576114a18686838181106114605761146061362e565b9050602002016020810190611475919061322e565b8585848181106114875761148761362e565b905060200201602081019061149c91906130f7565b6126a3565b600101611443565b505050505050565b5f805f805f805f6114c25f896111e4565b959e949d50929b5090995097509550909350915050565b5f6114e382612558565b6001600160a01b03939093165f90815260029093016020525050604090205460ff1690565b60366020525f908152604090208054819061152290613642565b80601f016020809104026020016040519081016040528092919081815260200182805461154e90613642565b80156115995780601f1061157057610100808354040283529160200191611599565b820191905f5260205f20905b81548152906001019060200180831161157c57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6112d882612886565b6026546040516304f65f8b60e21b81523060048201526001600160a01b038481166024830152604482018490525f9283928392839216906313d97e2c906064016040805180830381865afa158015611619573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061163d91906135de565b909450925050505b9250929050565b6001600160a01b0381165f90815260086020908152604080832080548251818502810185019093528083526060949384939291908301828280156116b757602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611699575b505050505090505f815190505f8167ffffffffffffffff8111156116dd576116dd613470565b604051908082528060200260200182016040528015611706578160200160208202803683370190505b5090505f5b8281101561179c575f6117368583815181106117295761172961362e565b6020026020010151612558565b805490915060ff1615611793578482815181106117555761175561362e565b602002602001015183878151811061176f5761176f61362e565b6001600160a01b03909216602092830291909101909101526117908661368e565b95505b5060010161170b565b5092835250909392505050565b6001600160a01b0382165f9081526035602052604081205481906117d6906001600160601b0316846125f1565b9695505050505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561183657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611818575b5050505050905090565b6060815f8167ffffffffffffffff81111561185d5761185d613470565b604051908082528060200260200182016040528015611886578160200160208202803683370190505b5090505f5b828110156113eb576118c38686838181106118a8576118a861362e565b90506020020160208101906118bd91906130f7565b336129ba565b60148111156118d4576118d46135ca565b8282815181106118e6576118e661362e565b602090810291909101015260010161188b565b602654604051630779996560e11b81523060048201526001600160a01b0385811660248301528481166044830152606482018490525f928392839283921690630ef332ca906084016040805180830381865afa15801561195b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197f91906135de565b909890975095505050505050565b5f6119c160405180604001604052806012815260200171637265617465506f6f6c28737472696e672960701b8152506124a8565b81515f036119e25760405163522e397360e11b815260040160405180910390fd5b603780545f919082906119fd906001600160601b03166136a6565b82546001600160601b038083166101009490940a848102910219909116179092555f90815260366020526040902090915080611a39858261370f565b5060028101805460ff191660011790556040516001600160601b038316907fc419386a8582a5374f4db03fdbb9fd99c73ef32d6ce9fc3a8c249e97bf31f9af90611a849087906137cb565b60405180910390a25092915050565b611ad16040518060400160405280602081526020017f72656d6f7665506f6f6c4d61726b65742875696e7439362c61646472657373298152506124a8565b6001600160601b038216611af857604051630203217b60e61b815260040160405180910390fd5b5f611b0383836112bd565b5f8181526009602052604090205490915060ff16611b4e576040516338ddb96b60e11b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c8c565b6001600160601b0383165f908152603660205260408120600101805490915b81811015611c5b57846001600160a01b0316838281548110611b9157611b9161362e565b5f918252602090912001546001600160a01b031603611c535782611bb66001846137dd565b81548110611bc657611bc661362e565b905f5260205f20015f9054906101000a90046001600160a01b0316838281548110611bf357611bf361362e565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480611c2e57611c2e6137f0565b5f8281526020902081015f1990810180546001600160a01b0319169055019055611c5b565b600101611b6d565b505f83815260096020526040808220805460ff199081168255600182018490556003820180549091169055600481018390556005810183905560060180546cffffffffffffffffffffffffff19169055516001600160a01b038616916001600160601b038816917fc8bef274db6d8c804aba68a69e64268bcfe7dd0aead2efcec0cac73a2df56e129190a35050505050565b5f336001600160a01b03841614801590611d2a57506001600160a01b0383165f908152602c6020908152604080832033845290915290205460ff16155b15611d48576040516337248ad960e01b815260040160405180910390fd5b611d5282846129ba565b6014811115610c3257610c326135ca565b5f80611d6f5f846125f1565b95945050505050565b6008602052815f5260405f208181548110611d91575f80fd5b5f918252602090912001546001600160a01b03169150829050565b611db582612a8d565b335f908152602c602090815260408083206001600160a01b038616845290915290205481151560ff909116151503611e2f5760405162461bcd60e51b815260206004820152601b60248201527f44656c65676174696f6e2073746174757320756e6368616e67656400000000006044820152606401610c8c565b611e3a338383612adb565b5050565b6001600160a01b0382165f90815260296020526040812081836008811115611e6857611e686135ca565b815260208101919091526040015f205460ff169392505050565b5f611e8e826008612b47565b6040516361bfb47160e11b815233600482015282905f90819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa158015611ed8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611efc9190613804565b50925092509250825f14611f525760405162461bcd60e51b815260206004820152601960248201527f6765744163636f756e74536e617073686f74206661696c6564000000000000006044820152606401610c8c565b8015611f64576117d6600c600261257a565b5f611f70873385612b91565b90508015611f9057611f85600e600383612c38565b979650505050505050565b5f611f9a86612558565b335f90815260028201602052604090205490915060ff16611fc2575f98975050505050505050565b335f9081526002820160209081526040808320805460ff1916905560089091528120805490915b818110156120d757886001600160a01b031683828154811061200d5761200d61362e565b5f918252602090912001546001600160a01b0316036120cf57826120326001846137dd565b815481106120425761204261362e565b905f5260205f20015f9054906101000a90046001600160a01b031683828154811061206f5761206f61362e565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550828054806120aa576120aa6137f0565b5f8281526020902081015f1990810180546001600160a01b03191690550190556120d7565b600101611fe9565b8181106120e6576120e6613837565b60405133906001600160a01b038b16907fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d905f90a35f9b9a5050505050505050505050565b6001600160a01b0382165f9081526008602090815260408083208054825181850281018501909352808352849383018282801561218f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612171575b50939450505050506001600160601b038316158015906121c557506001600160a01b0384165f9081526016602052604090205415155b156121d3575f9150506112d8565b5f5b81518110156122af575f8282815181106121f1576121f161362e565b602002602001015190505f61220686836112bd565b5f81815260096020526040902060060154909150600160601b900460ff166122a5576040516395dd919360e01b81526001600160a01b0388811660048301525f91908416906395dd919390602401602060405180830381865afa15801561226f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612293919061384b565b11156122a5575f9450505050506112d8565b50506001016121d5565b506001949350505050565b6037546001600160601b0390811690821611156122f557604051632db8671b60e11b81526001600160601b0382166004820152602401610c8c565b335f908152603560205260409020546001600160601b039081169082160361233057604051631c9d4f3960e31b815260040160405180910390fd5b6001600160601b0381161580159061236357506001600160601b0381165f9081526036602052604090206002015460ff16155b1561238c57604051632da4cc0560e01b81526001600160601b0382166004820152602401610c8c565b612396338261212b565b6123b35760405163592ec11d60e01b815260040160405180910390fd5b335f818152603560209081526040918290205491516001600160601b03928316815291841692917f9181876220501cdac3aa7278fd34e9bd150c30a27b6ed95458fe859761b071f7910160405180910390a3335f81815260356020526040812080546bffffffffffffffffffffffff19166001600160601b0385161790559081906124419082808080612cb7565b9193509091505f905082601481111561245c5761245c6135ca565b14158061246857505f81115b156124a35781601481111561247f5761247f6135ca565b60405163c978466160e01b8152600481019190915260248101829052604401610c8c565b505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906124da9033908590600401613862565b602060405180830381865afa1580156124f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125199190613885565b6125555760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610c8c565b50565b5f60095f6125665f856112bd565b81526020019081526020015f209050919050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360148111156125ae576125ae6135ca565b83601a8111156125c0576125c06135ca565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610c3257610c326135ca565b6001600160601b0382165f818152603660205260408120909182918291829015806126215750600282015460ff16155b156126365761262f86612558565b9050612685565b5f61264188886112bd565b5f81815260096020526040902080549192509060ff1615801561266d57506002840154610100900460ff165b6126775780612680565b61268088612558565b925050505b80600101548160040154826005015494509450945050509250925092565b6001600160601b0382166126ca57604051630203217b60e61b815260040160405180910390fd5b6037546001600160601b03908116908316111561270557604051632db8671b60e11b81526001600160601b0383166004820152602401610c8c565b6001600160601b0382165f9081526036602052604090206002015460ff1661274b57604051632da4cc0560e01b81526001600160601b0383166004820152602401610c8c565b5f6127565f836112bd565b5f8181526009602052604090205490915060ff16612787576040516386dccab760e01b815260040160405180910390fd5b61279183836112bd565b5f8181526009602052604090205490915060ff16156127dd5760405163d9d72f2b60e01b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c8c565b5f8181526009602090815260408083206006810180546bffffffffffffffffffffffff19166001600160601b038916908117909155815460ff19166001908117835581865260368552838620810180549182018155865293852090930180546001600160a01b0319166001600160a01b038816908117909155915190939192917f2159e9508e372ac69e1047a124c5478445206066e5d7df7e4214a1986cd78c8091a350505050565b5f6128c56040518060400160405280601781526020017f5f737570706f72744d61726b65742861646472657373290000000000000000008152506124a8565b6128ce82612558565b5460ff16156128e3576112d8600a601161257a565b816001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561291f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129439190613885565b505f61294e83612558565b8054600160ff19918216811783556003830180549092169091555f90820155905061297883612d80565b61298183612e56565b6040516001600160a01b038416907fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f905f90a25f610c32565b5f6129c6836007612b47565b5f6129d084612558565b90506129db81612f18565b6001600160a01b0383165f90815260028201602052604090205460ff1615612a06575f9150506112d8565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b6001600160a01b0381166125555760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610c8c565b6001600160a01b038381165f818152602c6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fcb325b7784f78486e42849c7a50b8c5ee008d00cd90e108a58912c0fcb6288b4910160405180910390a3505050565b612b518282611e3e565b15611e3a5760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610c8c565b5f612ba3612b9e85612558565b612f18565b612bac84612558565b6001600160a01b0384165f908152600291909101602052604090205460ff16612bd657505f610c32565b5f80612be58587865f80612cb7565b9193509091505f9050826014811115612c0057612c006135ca565b14612c2057816014811115612c1757612c176135ca565b92505050610c32565b8015612c2d576004612c17565b5f9695505050505050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846014811115612c6c57612c6c6135ca565b84601a811115612c7e57612c7e6135ca565b604080519283526020830191909152810184905260600160405180910390a1836014811115612caf57612caf6135ca565b949350505050565b5f808080846001811115612ccd57612ccd6135ca565b03612cdb57612cdb88612f5d565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e90612d199030908f908f908f908f908f906004016138a0565b606060405180830381865afa158015612d34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d5891906138db565b925092509250826014811115612d7057612d706135ca565b9b919a5098509650505050505050565b600d545f5b81811015612e0357826001600160a01b0316600d8281548110612daa57612daa61362e565b5f918252602090912001546001600160a01b031603612dfb5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481859191959609a1b6044820152606401610c8c565b600101612d85565b5050600d80546001810182555f919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b5f612e5f61307b565b6001600160a01b0383165f908152601060209081526040808320601190925282208154939450909290916001600160e01b039091169003612eba5781546001600160e01b0319166ec097ce7bc90715b34b9f10000000001782555b80546001600160e01b03165f03612eeb5780546001600160e01b0319166ec097ce7bc90715b34b9f10000000001781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b805460ff166125555760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610c8c565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015612fd357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612fb5575b505083519394505f925050505b8181101561307457836001600160a01b031663a9c3cab18483815181106130095761300961362e565b60200260200101516040518263ffffffff1660e01b815260040161303c91906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015613053575f80fd5b505af1158015613065573d5f803e3d5ffd5b50505050806001019050612fe0565b5050505050565b5f6130af4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b8152506130b4565b905090565b5f8164010000000084106130db5760405162461bcd60e51b8152600401610c8c91906137cb565b509192915050565b6001600160a01b0381168114612555575f80fd5b5f60208284031215613107575f80fd5b8135610c32816130e3565b5f8060408385031215613123575f80fd5b823561312e816130e3565b9150602083013561313e816130e3565b809150509250929050565b5f805f806080858703121561315c575f80fd5b8435613167816130e3565b93506020850135613177816130e3565b92506040850135613187816130e3565b9396929550929360600135925050565b5f805f606084860312156131a9575f80fd5b83356131b4816130e3565b925060208401356131c4816130e3565b91506040840135600281106131d7575f80fd5b809150509250925092565b80356001600160601b03811681146131f8575f80fd5b919050565b5f806040838503121561320e575f80fd5b61312e836131e2565b5f60208284031215613227575f80fd5b5035919050565b5f6020828403121561323e575f80fd5b610c32826131e2565b602080825282518282018190525f9190848201906040850190845b818110156132875783516001600160a01b031683529284019291840191600101613262565b50909695505050505050565b5f8083601f8401126132a3575f80fd5b50813567ffffffffffffffff8111156132ba575f80fd5b6020830191508360208260051b8501011115611645575f80fd5b5f805f80604085870312156132e7575f80fd5b843567ffffffffffffffff808211156132fe575f80fd5b61330a88838901613293565b90965094506020870135915080821115613322575f80fd5b5061332f87828801613293565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61337b606083018661333b565b931515602083015250901515604090910152919050565b5f80604083850312156133a3575f80fd5b82356133ae816130e3565b946020939093013593505050565b5f80602083850312156133cd575f80fd5b823567ffffffffffffffff8111156133e3575f80fd5b6133ef85828601613293565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b8181101561328757835183529284019291840191600101613416565b5f805f60608486031215613444575f80fd5b833561344f816130e3565b9250602084013561345f816130e3565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215613494575f80fd5b813567ffffffffffffffff808211156134ab575f80fd5b818401915084601f8301126134be575f80fd5b8135818111156134d0576134d0613470565b604051601f8201601f19908116603f011681019083821181831017156134f8576134f8613470565b81604052828152876020848701011115613510575f80fd5b826020860160208301375f928101602001929092525095945050505050565b8015158114612555575f80fd5b5f806040838503121561354d575f80fd5b8235613558816130e3565b9150602083013561313e8161352f565b5f8060408385031215613579575f80fd5b8235613584816130e3565b915060208301356009811061313e575f80fd5b5f80604083850312156135a8575f80fd5b82356135b3816130e3565b91506135c1602084016131e2565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156135ef575f80fd5b505080516020909101519092909150565b6002811061361c57634e487b7160e01b5f52602160045260245ffd5b9052565b602081016112d88284613600565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061365657607f821691505b60208210810361367457634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161369f5761369f61367a565b5060010190565b5f6001600160601b038083168181036136c1576136c161367a565b6001019392505050565b601f8211156124a357805f5260205f20601f840160051c810160208510156136f05750805b601f840160051c820191505b81811015613074575f81556001016136fc565b815167ffffffffffffffff81111561372957613729613470565b61373d816137378454613642565b846136cb565b602080601f831160018114613770575f84156137595750858301515b5f19600386901b1c1916600185901b1785556114a9565b5f85815260208120601f198616915b8281101561379e5788860151825594840194600190910190840161377f565b50858210156137bb57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b602081525f610c32602083018461333b565b818103818111156112d8576112d861367a565b634e487b7160e01b5f52603160045260245ffd5b5f805f8060808587031215613817575f80fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b5f52600160045260245ffd5b5f6020828403121561385b575f80fd5b5051919050565b6001600160a01b03831681526040602082018190525f90612caf9083018461333b565b5f60208284031215613895575f80fd5b8151610c328161352f565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101611f8560a0830184613600565b5f805f606084860312156138ed575f80fd5b835192506020840151915060408401519050925092509256fe616464506f6f6c4d61726b6574732875696e7439365b5d2c616464726573735b5d29a26469706673582212203504412fc390ce3c0a3481ff369b4e1708c86eb2a968acc7786b35dd85f2e44364736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This facet contains all the methods related to the market's management in the pool", @@ -2369,6 +2382,9 @@ "createPool(string)": { "notice": "Creates a new pool with the given label." }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "enterMarketBehalf(address,address)": { "notice": "Add assets to be included in account liquidity calculation" }, @@ -2544,7 +2560,7 @@ "storageLayout": { "storage": [ { - "astId": 4875, + "astId": 9226, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "admin", "offset": 0, @@ -2552,7 +2568,7 @@ "type": "t_address" }, { - "astId": 4878, + "astId": 9229, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "pendingAdmin", "offset": 0, @@ -2560,7 +2576,7 @@ "type": "t_address" }, { - "astId": 4881, + "astId": 9232, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "comptrollerImplementation", "offset": 0, @@ -2568,7 +2584,7 @@ "type": "t_address" }, { - "astId": 4884, + "astId": 9235, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -2576,15 +2592,15 @@ "type": "t_address" }, { - "astId": 4891, + "astId": 9242, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)3797" + "type": "t_contract(ResilientOracleInterface)7913" }, { - "astId": 4894, + "astId": 9245, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "closeFactorMantissa", "offset": 0, @@ -2592,7 +2608,7 @@ "type": "t_uint256" }, { - "astId": 4897, + "astId": 9248, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -2600,7 +2616,7 @@ "type": "t_uint256" }, { - "astId": 4900, + "astId": 9251, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "maxAssets", "offset": 0, @@ -2608,23 +2624,23 @@ "type": "t_uint256" }, { - "astId": 4907, + "astId": 9258, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)40234)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)" }, { - "astId": 4941, + "astId": 9292, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)14658,t_struct(Market)4934_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)" }, { - "astId": 4944, + "astId": 9295, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "pauseGuardian", "offset": 0, @@ -2632,7 +2648,7 @@ "type": "t_address" }, { - "astId": 4947, + "astId": 9298, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -2640,7 +2656,7 @@ "type": "t_bool" }, { - "astId": 4950, + "astId": 9301, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -2648,7 +2664,7 @@ "type": "t_bool" }, { - "astId": 4953, + "astId": 9304, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "transferGuardianPaused", "offset": 22, @@ -2656,7 +2672,7 @@ "type": "t_bool" }, { - "astId": 4956, + "astId": 9307, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -2664,7 +2680,7 @@ "type": "t_bool" }, { - "astId": 4961, + "astId": 9312, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "mintGuardianPaused", "offset": 0, @@ -2672,7 +2688,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 4966, + "astId": 9317, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -2680,15 +2696,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 4978, + "astId": 9329, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)40234)dyn_storage" + "type": "t_array(t_contract(VToken)49461)dyn_storage" }, { - "astId": 4981, + "astId": 9332, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusRate", "offset": 0, @@ -2696,7 +2712,7 @@ "type": "t_uint256" }, { - "astId": 4986, + "astId": 9337, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusSpeeds", "offset": 0, @@ -2704,23 +2720,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 4992, + "astId": 9343, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)4973_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 4998, + "astId": 9349, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)4973_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 5005, + "astId": 9356, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusSupplierIndex", "offset": 0, @@ -2728,7 +2744,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 5012, + "astId": 9363, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -2736,7 +2752,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 5017, + "astId": 9368, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusAccrued", "offset": 0, @@ -2744,15 +2760,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5021, + "astId": 9372, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)33333" + "type": "t_contract(VAIControllerInterface)42511" }, { - "astId": 5026, + "astId": 9377, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "mintedVAIs", "offset": 0, @@ -2760,7 +2776,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5029, + "astId": 9380, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "vaiMintRate", "offset": 0, @@ -2768,7 +2784,7 @@ "type": "t_uint256" }, { - "astId": 5032, + "astId": 9383, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -2776,7 +2792,7 @@ "type": "t_bool" }, { - "astId": 5034, + "astId": 9385, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -2784,7 +2800,7 @@ "type": "t_bool" }, { - "astId": 5037, + "astId": 9388, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "protocolPaused", "offset": 2, @@ -2792,7 +2808,7 @@ "type": "t_bool" }, { - "astId": 5040, + "astId": 9391, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusVAIRate", "offset": 0, @@ -2800,7 +2816,7 @@ "type": "t_uint256" }, { - "astId": 5046, + "astId": 9397, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -2808,7 +2824,7 @@ "type": "t_uint256" }, { - "astId": 5048, + "astId": 9399, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "vaiVaultAddress", "offset": 0, @@ -2816,7 +2832,7 @@ "type": "t_address" }, { - "astId": 5050, + "astId": 9401, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "releaseStartBlock", "offset": 0, @@ -2824,7 +2840,7 @@ "type": "t_uint256" }, { - "astId": 5052, + "astId": 9403, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "minReleaseAmount", "offset": 0, @@ -2832,7 +2848,7 @@ "type": "t_uint256" }, { - "astId": 5058, + "astId": 9409, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "borrowCapGuardian", "offset": 0, @@ -2840,7 +2856,7 @@ "type": "t_address" }, { - "astId": 5063, + "astId": 9414, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "borrowCaps", "offset": 0, @@ -2848,7 +2864,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5069, + "astId": 9420, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "treasuryGuardian", "offset": 0, @@ -2856,7 +2872,7 @@ "type": "t_address" }, { - "astId": 5072, + "astId": 9423, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "treasuryAddress", "offset": 0, @@ -2864,7 +2880,7 @@ "type": "t_address" }, { - "astId": 5075, + "astId": 9426, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "treasuryPercent", "offset": 0, @@ -2872,7 +2888,7 @@ "type": "t_uint256" }, { - "astId": 5083, + "astId": 9434, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -2880,7 +2896,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5088, + "astId": 9439, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "lastContributorBlock", "offset": 0, @@ -2888,7 +2904,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5093, + "astId": 9444, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "liquidatorContract", "offset": 0, @@ -2896,15 +2912,15 @@ "type": "t_address" }, { - "astId": 5099, + "astId": 9450, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)4858" + "type": "t_contract(ComptrollerLensInterface)9207" }, { - "astId": 5107, + "astId": 9458, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "supplyCaps", "offset": 0, @@ -2912,7 +2928,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5113, + "astId": 9464, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "accessControl", "offset": 0, @@ -2920,7 +2936,7 @@ "type": "t_address" }, { - "astId": 5120, + "astId": 9471, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_actionPaused", "offset": 0, @@ -2928,7 +2944,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 5128, + "astId": 9479, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -2936,7 +2952,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5133, + "astId": 9484, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -2944,7 +2960,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5143, + "astId": 9494, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "approvedDelegates", "offset": 0, @@ -2952,7 +2968,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 5151, + "astId": 9502, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -2960,23 +2976,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 5170, + "astId": 9521, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)5159_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)" }, { - "astId": 5175, + "astId": 9526, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)5165_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)" }, { - "astId": 5178, + "astId": 9529, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_facetAddresses", "offset": 0, @@ -2984,15 +3000,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 5185, + "astId": 9536, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)30511" + "type": "t_contract(IPrime)33730" }, { - "astId": 5195, + "astId": 9546, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -3000,7 +3016,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 5201, + "astId": 9552, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "xvs", "offset": 0, @@ -3008,7 +3024,7 @@ "type": "t_address" }, { - "astId": 5204, + "astId": 9555, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "xvsVToken", "offset": 0, @@ -3016,7 +3032,7 @@ "type": "t_address" }, { - "astId": 5226, + "astId": 9577, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "userPoolId", "offset": 0, @@ -3024,15 +3040,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 5232, + "astId": 9583, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)5221_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)9572_storage)" }, { - "astId": 5235, + "astId": 9586, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "lastPoolId", "offset": 0, @@ -3040,7 +3056,7 @@ "type": "t_uint96" }, { - "astId": 5243, + "astId": 9594, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -3048,12 +3064,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 5246, + "astId": 9597, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 9604, + "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)7883" } ], "types": { @@ -3074,8 +3098,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)40234)dyn_storage": { - "base": "t_contract(VToken)40234", + "t_array(t_contract(VToken)49461)dyn_storage": { + "base": "t_contract(VToken)49461", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -3090,37 +3114,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)4858": { + "t_contract(ComptrollerLensInterface)9207": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)30511": { + "t_contract(IDeviationBoundedOracle)7883": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)33730": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)3797": { + "t_contract(ResilientOracleInterface)7913": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)33333": { + "t_contract(VAIControllerInterface)42511": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)40234": { + "t_contract(VToken)49461": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)40234)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)40234)dyn_storage" + "value": "t_array(t_contract(VToken)49461)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -3150,19 +3179,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)5165_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)5165_storage" + "value": "t_struct(FacetFunctionSelectors)9516_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)4973_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)4973_storage" + "value": "t_struct(VenusMarketState)9324_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -3178,12 +3207,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)5159_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)5159_storage" + "value": "t_struct(FacetAddressAndPosition)9510_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -3192,31 +3221,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)5221_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)9572_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)5221_storage" + "value": "t_struct(PoolData)9572_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)14658,t_struct(Market)4934_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)14658", + "key": "t_userDefinedValueType(PoolMarketId)19217", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)4934_storage" + "value": "t_struct(Market)9285_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)5159_storage": { + "t_struct(FacetAddressAndPosition)9510_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 5156, + "astId": 9507, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "facetAddress", "offset": 0, @@ -3224,7 +3253,7 @@ "type": "t_address" }, { - "astId": 5158, + "astId": 9509, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "functionSelectorPosition", "offset": 20, @@ -3234,12 +3263,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)5165_storage": { + "t_struct(FacetFunctionSelectors)9516_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 5162, + "astId": 9513, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "functionSelectors", "offset": 0, @@ -3247,7 +3276,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 5164, + "astId": 9515, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "facetAddressPosition", "offset": 0, @@ -3257,12 +3286,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)4934_storage": { + "t_struct(Market)9285_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 4910, + "astId": 9261, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isListed", "offset": 0, @@ -3270,7 +3299,7 @@ "type": "t_bool" }, { - "astId": 4913, + "astId": 9264, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -3278,7 +3307,7 @@ "type": "t_uint256" }, { - "astId": 4918, + "astId": 9269, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "accountMembership", "offset": 0, @@ -3286,7 +3315,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 4921, + "astId": 9272, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isVenus", "offset": 0, @@ -3294,7 +3323,7 @@ "type": "t_bool" }, { - "astId": 4924, + "astId": 9275, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -3302,7 +3331,7 @@ "type": "t_uint256" }, { - "astId": 4927, + "astId": 9278, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -3310,7 +3339,7 @@ "type": "t_uint256" }, { - "astId": 4930, + "astId": 9281, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "poolId", "offset": 0, @@ -3318,7 +3347,7 @@ "type": "t_uint96" }, { - "astId": 4933, + "astId": 9284, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isBorrowAllowed", "offset": 12, @@ -3328,12 +3357,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)5221_storage": { + "t_struct(PoolData)9572_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 5210, + "astId": 9561, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "label", "offset": 0, @@ -3341,7 +3370,7 @@ "type": "t_string_storage" }, { - "astId": 5214, + "astId": 9565, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "vTokens", "offset": 0, @@ -3349,7 +3378,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 5217, + "astId": 9568, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isActive", "offset": 0, @@ -3357,7 +3386,7 @@ "type": "t_bool" }, { - "astId": 5220, + "astId": 9571, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -3367,12 +3396,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)4973_storage": { + "t_struct(VenusMarketState)9324_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 4969, + "astId": 9320, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "index", "offset": 0, @@ -3380,7 +3409,7 @@ "type": "t_uint224" }, { - "astId": 4972, + "astId": 9323, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "block", "offset": 28, @@ -3410,7 +3439,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)14658": { + "t_userDefinedValueType(PoolMarketId)19217": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bscmainnet/PolicyFacet.json b/deployments/bscmainnet/PolicyFacet.json index 4d4cc3199..5c0867b53 100644 --- a/deployments/bscmainnet/PolicyFacet.json +++ b/deployments/bscmainnet/PolicyFacet.json @@ -1,5 +1,5 @@ { - "address": "0x3C115aA5800A589D1E0c3163f3f562D5544F060f", + "address": "0x1CcDaf39085bae4e27c3Ba100561b1AD1B5A6b80", "abi": [ { "inputs": [], @@ -655,6 +655,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -1755,28 +1768,28 @@ "type": "function" } ], - "transactionHash": "0xd5df3172ee0e34a0cf8f02e1f8ceacc038ac9bd707f922efadbdcd5b5c4cad41", + "transactionHash": "0x911bcd68c49d3c9f832d15d2599f47118a2a8a85fad71239751f632c312f17f8", "receipt": { "to": null, - "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x3C115aA5800A589D1E0c3163f3f562D5544F060f", - "transactionIndex": 106, - "gasUsed": "2997657", + "from": "0x9b0A3EAE7f174937d31745B710BbeA68e9D1BEf7", + "contractAddress": "0x1CcDaf39085bae4e27c3Ba100561b1AD1B5A6b80", + "transactionIndex": 51, + "gasUsed": "3095497", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2649bfb863a4074f37c377a90603866d66c97d95087235fcc060d0204253656b", - "transactionHash": "0xd5df3172ee0e34a0cf8f02e1f8ceacc038ac9bd707f922efadbdcd5b5c4cad41", + "blockHash": "0x52aeffb52f7021634fa820186b4da6681048f09128f078a20de5a98ac7516174", + "transactionHash": "0x911bcd68c49d3c9f832d15d2599f47118a2a8a85fad71239751f632c312f17f8", "logs": [], - "blockNumber": 66294685, - "cumulativeGasUsed": "19057203", + "blockNumber": 95559330, + "cumulativeGasUsed": "10026659", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"VenusBorrowSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"VenusSupplySpeedUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"supplySpeeds\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"borrowSpeeds\",\"type\":\"uint256[]\"}],\"name\":\"_setVenusSpeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getBorrowingPower\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the hooks used while transferring the assets\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setVenusSpeeds(address[],uint256[],uint256[])\":{\"details\":\"Allows the contract admin to set XVS speed for a market\",\"params\":{\"borrowSpeeds\":\"New XVS speed for borrow\",\"supplySpeeds\":\"New XVS speed for supply\",\"vTokens\":\"The market whose XVS speed to update\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"vToken\":\"The market to verify the borrow against\"},\"returns\":{\"_0\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"vToken\":\"Asset whose underlying is being borrowed\"}},\"getAccountLiquidity(address)\":{\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), account liquidity in excess of liquidation threshold requirements, account shortfall below liquidation threshold requirements)\"}},\"getBorrowingPower(address)\":{\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"}},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\",\"vTokenModify\":\"The market to hypothetically redeem/borrow in\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The amount of collateral token that will be seized\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"mintAllowed(address,address,uint256)\":{\"params\":{\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\",\"vToken\":\"The market to verify the mint against\"},\"returns\":{\"_0\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\",\"vToken\":\"Asset being minted\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"redeemTokens\":\"The number of vTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\",\"vToken\":\"The market to verify the redeem against\"},\"returns\":{\"_0\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\",\"vToken\":\"Asset being redeemed\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which borrowed the asset\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\",\"vToken\":\"The market to verify the repay against\"},\"returns\":{\"_0\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"payer\":\"The address repaying the borrow\",\"vToken\":\"Asset being repaid\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"The market to verify the transfer against\"},\"returns\":{\"_0\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"Asset being transferred\"}}},\"title\":\"PolicyFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedBorrowerVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a borrower\"},\"DistributedSupplierVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a supplier\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"VenusBorrowSpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new borrow-side XVS speed is calculated for a market\"},\"VenusSupplySpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new supply-side XVS speed is calculated for a market\"}},\"kind\":\"user\",\"methods\":{\"_setVenusSpeeds(address[],uint256[],uint256[])\":{\"notice\":\"Set XVS speed for a single market\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt liquidation threshold requirements\"},\"getBorrowingPower(address)\":{\"notice\":\"Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains all the external pre-hook functions related to vToken\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/PolicyFacet.sol\":\"PolicyFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/PolicyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IPolicyFacet } from \\\"../interfaces/IPolicyFacet.sol\\\";\\n\\nimport { XVSRewardsHelper } from \\\"./XVSRewardsHelper.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title PolicyFacet\\n * @author Venus\\n * @dev This facet contains all the hooks used while transferring the assets\\n * @notice This facet contract contains all the external pre-hook functions related to vToken\\n */\\ncontract PolicyFacet is IPolicyFacet, XVSRewardsHelper {\\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.MINT);\\n ensureListed(getCorePoolMarket(vToken));\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n require(supplyCap != 0, \\\"market supply cap is 0\\\");\\n\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n require(nextTotalSupply <= supplyCap, \\\"market supply cap reached\\\");\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, minter);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n // solhint-disable-next-line no-unused-vars\\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(minter, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.REDEEM);\\n\\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\\n if (allowed != uint256(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, redeemer);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\\n require(redeemTokens != 0 || redeemAmount == 0, \\\"redeemTokens zero\\\");\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.BORROW);\\n ensureListed(getCorePoolMarket(vToken));\\n poolBorrowAllowed(borrower, vToken);\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n require(borrowCap != 0, \\\"market borrow cap is 0\\\");\\n\\n if (!getCorePoolMarket(vToken).accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == vToken, \\\"sender must be vToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(VToken(vToken), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n }\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n return uint256(Error.PRICE_ERROR);\\n }\\n\\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\\n require(nextTotalBorrows <= borrowCap, \\\"market borrow cap reached\\\");\\n\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n updateVenusBorrowIndex(vToken, borrowIndex);\\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n // solhint-disable-next-line no-unused-vars\\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address vToken,\\n address payer, // solhint-disable-line no-unused-vars\\n address borrower,\\n uint256 repayAmount // solhint-disable-line no-unused-vars\\n ) external returns (uint256) {\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.REPAY);\\n ensureListed(getCorePoolMarket(vToken));\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n updateVenusBorrowIndex(vToken, borrowIndex);\\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address vToken,\\n address payer, // solhint-disable-line no-unused-vars\\n address borrower,\\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount\\n ) external view returns (uint256) {\\n checkProtocolPauseState();\\n\\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\\n return uint256(Error.UNAUTHORIZED);\\n }\\n\\n ensureListed(getCorePoolMarket(vTokenCollateral));\\n uint256 borrowBalance;\\n if (address(vTokenBorrowed) != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n } else {\\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\\n }\\n\\n if (isForcedLiquidationEnabled[vTokenBorrowed] || isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n return uint(Error.TOO_MUCH_REPAY);\\n }\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n borrower,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_LIQUIDATION_THRESHOLD\\n );\\n\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall == 0) {\\n return uint256(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n // The liquidator may not repay more than what is allowed by the closeFactor\\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\\n return uint256(Error.TOO_MUCH_REPAY);\\n }\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n * @param seizeTokens The amount of collateral token that will be seized\\n */\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral, // solhint-disable-line no-unused-vars\\n address liquidator,\\n address borrower,\\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = getCorePoolMarket(vTokenCollateral);\\n\\n // We've added VAIController as a borrowed token list check for seize\\n ensureListed(market);\\n\\n if (!market.accountMembership[borrower]) {\\n return uint256(Error.MARKET_NOT_COLLATERAL);\\n }\\n\\n if (address(vTokenBorrowed) != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n\\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\\n return uint256(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vTokenCollateral);\\n distributeSupplierVenus(vTokenCollateral, borrower);\\n distributeSupplierVenus(vTokenCollateral, liquidator);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\\n if (allowed != uint256(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, src);\\n distributeSupplierVenus(vToken, dst);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n */\\n // solhint-disable-next-line no-unused-vars\\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(src, vToken);\\n prime.accrueInterestAndUpdateScore(dst, vToken);\\n }\\n }\\n\\n /**\\n * @notice Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\\n * @param account The account get liquidity for\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) {\\n return _getAccountLiquidity(account, WeightFunction.USE_COLLATERAL_FACTOR);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt liquidation threshold requirements\\n * @param account The account get liquidity for\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of liquidation threshold requirements,\\n * account shortfall below liquidation threshold requirements)\\n */\\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\\n return _getAccountLiquidity(account, WeightFunction.USE_LIQUIDATION_THRESHOLD);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n return (uint256(err), liquidity, shortfall);\\n }\\n\\n // setter functionality\\n /**\\n * @notice Set XVS speed for a single market\\n * @dev Allows the contract admin to set XVS speed for a market\\n * @param vTokens The market whose XVS speed to update\\n * @param supplySpeeds New XVS speed for supply\\n * @param borrowSpeeds New XVS speed for borrow\\n */\\n function _setVenusSpeeds(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplySpeeds,\\n uint256[] calldata borrowSpeeds\\n ) external {\\n ensureAdmin();\\n\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n ensureNonzeroAddress(address(vTokens[i]));\\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @dev Internal function to set XVS speed for a single market\\n * @param vToken The market whose XVS speed to update\\n * @param supplySpeed New XVS speed for supply\\n * @param borrowSpeed New XVS speed for borrow\\n * @custom:event VenusSupplySpeedUpdated Emitted after the venus supply speed for a market is updated\\n * @custom:event VenusBorrowSpeedUpdated Emitted after the venus borrow speed for a market is updated\\n */\\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n ensureListed(getCorePoolMarket(address(vToken)));\\n\\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. XVS accrued properly for the old speed, and\\n // 2. XVS accrued at the new speed starts after this block.\\n\\n updateVenusSupplyIndex(address(vToken));\\n // Update speed and emit event\\n venusSupplySpeeds[address(vToken)] = supplySpeed;\\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. XVS accrued properly for the old speed, and\\n // 2. XVS accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n updateVenusBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @dev Checks if vToken borrowing is allowed in the account's entered pool\\n * Reverts if borrowing is not permitted\\n * @param account The address of the account whose borrow permission is being checked\\n * @param vToken The vToken market to check borrowing status for\\n * @custom:error BorrowNotAllowedInPool Reverts if borrowing is not allowed in the account's entered pool\\n * @custom:error InactivePool Reverts if borrowing in an inactive pool.\\n */\\n function poolBorrowAllowed(address account, address vToken) internal view {\\n uint96 userPool = userPoolId[account];\\n PoolMarketId index = getPoolMarketIndex(userPool, vToken);\\n if (!_poolMarkets[index].isBorrowAllowed) {\\n revert BorrowNotAllowedInPool();\\n }\\n if (userPool != corePoolId && !pools[userPool].isActive) {\\n revert InactivePool(userPool);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x80f1a0df314b19d4d657001edb84718a132abe2382d1ad33d4b06607f51932f4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\n\\n/**\\n * @title XVSRewardsHelper\\n * @author Venus\\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\\n */\\ncontract XVSRewardsHelper is FacetBase {\\n /// @notice Emitted when XVS is distributed to a borrower\\n event DistributedBorrowerVenus(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 venusDelta,\\n uint256 venusBorrowIndex\\n );\\n\\n /// @notice Emitted when XVS is distributed to a supplier\\n event DistributedSupplierVenus(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 venusDelta,\\n uint256 venusSupplyIndex\\n );\\n\\n /**\\n * @notice Accrue XVS to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n */\\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\\n if (deltaBlocks != 0 && borrowSpeed != 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \\\"224\\\");\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n borrowState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Accrue XVS to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n */\\n function updateVenusSupplyIndex(address vToken) internal {\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n uint256 supplySpeed = venusSupplySpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\\n if (deltaBlocks != 0 && supplySpeed != 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \\\"224\\\");\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n supplyState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute XVS to\\n */\\n function distributeSupplierVenus(address vToken, address supplier) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 supplyIndex = venusSupplyState[vToken].index;\\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\\n // Update supplier's index to the current index since we are distributing accrued XVS\\n venusSupplierIndex[vToken][supplier] = supplyIndex;\\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n // Multiply of supplierTokens and supplierDelta\\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\\n // Addition of supplierAccrued and supplierDelta\\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute XVS to\\n */\\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 borrowIndex = venusBorrowState[vToken].index;\\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\\n // Update borrowers's index to the current index since we are distributing accrued XVS\\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0xf356db714f7aada286380ee5092b0a3e3163428943cfb5561ded76597e1c0c15\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IPolicyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IPolicyFacet {\\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\\n\\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\\n\\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\\n\\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) external returns (uint256);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint256 repayAmount,\\n uint256 borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount\\n ) external view returns (uint256);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n uint256 seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external returns (uint256);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external;\\n\\n function transferAllowed(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external returns (uint256);\\n\\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\\n\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256, uint256, uint256);\\n\\n function _setVenusSpeeds(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplySpeeds,\\n uint256[] calldata borrowSpeeds\\n ) external;\\n\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall);\\n}\\n\",\"keccak256\":\"0x6fd69f4b22548e9288f7c025d501966ae4f83132693a8e33f1e35ed55151d111\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506135308061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106103e0575f3560e01c80637dc0d1d01161020b578063c5f956af1161011f578063e0f6123d116100b4578063eabe7d9111610084578063eabe7d91146109ef578063ead1a8a014610a02578063f445d70314610a15578063f851a44014610a42578063fa6331d814610a54575f80fd5b8063e0f6123d1461097a578063e37d4b791461099c578063e85a2960146109d3578063e8755446146109e6575f80fd5b8063d463654c116100ef578063d463654c1461093a578063da3d454c14610941578063dce1544914610954578063dcfbc0c714610967575f80fd5b8063c5f956af146108ee578063c7ee005e14610901578063d02f735114610914578063d3270f9914610927575f80fd5b8063a657e579116101a0578063bbb8864a11610170578063bbb8864a14610875578063bdcdc25814610894578063bec04f72146108a7578063bf32442d146108b0578063c5b4db55146108c1575f80fd5b8063a657e579146107e1578063b2eafc39146107f4578063b8324c7c14610807578063bb82aa5e14610862575f80fd5b80639254f5e5116101db5780639254f5e51461079057806394b2294b146107a357806396c99064146107ac5780639bb27d62146107ce575f80fd5b80637dc0d1d01461072f5780637fb8e8cd146107425780638a7dc1651461074f5780638c1ac18a1461076e575f80fd5b80634a584432116103025780635dd3fc9d116102975780636d35bf91116102675780636d35bf91146106ae578063719f701b146106c157806373769099146106ca578063765513831461070a5780637d172bd51461071c575f80fd5b80635dd3fc9d146106565780635ec88c79146106755780635fc7e71e146106885780636a56947e1461069b575f80fd5b806351dff989116102d257806351dff9891461060a578063528a174c1461061d57806352d84d1e146106305780635c77860514610643575f80fd5b80634a584432146105975780634d99c776146105b65780634e79238f146105c95780634ef4c3e1146105f7575f80fd5b806324a3d6221161037857806341a18d2c1161034857806341a18d2c1461053457806341c728b91461055e578063425fad581461057157806347ef3b3b14610584575f80fd5b806324a3d622146104e257806326782247146104f55780632bc7e29e146105085780634088c73e14610527575f80fd5b806310b98338116103b357806310b98338146104525780631ededc911461048f57806321af4569146104a457806324008a62146104cf575f80fd5b806302c3bcbb146103e457806304ef9d581461041657806308e0225c1461041f5780630db4b4e514610449575b5f80fd5b6104036103f2366004612edf565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61040360225481565b61040361042d366004612efa565b601360209081525f928352604080842090915290825290205481565b610403601d5481565b61047f610460366004612efa565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161040d565b6104a261049d366004612f31565b610a5d565b005b601e546104b7906001600160a01b031681565b6040516001600160a01b03909116815260200161040d565b6104036104dd366004612f88565b610ad5565b600a546104b7906001600160a01b031681565b6001546104b7906001600160a01b031681565b610403610516366004612edf565b60166020525f908152604090205481565b60185461047f9060ff1681565b610403610542366004612efa565b601260209081525f928352604080842090915290825290205481565b6104a261056c366004612fd6565b610b8c565b60185461047f9062010000900460ff1681565b6104a2610592366004613019565b610c03565b6104036105a5366004612edf565b601f6020525f908152604090205481565b6104036105c436600461309e565b610cdb565b6105dc6105d7366004612fd6565b610cfc565b6040805193845260208401929092529082015260600161040d565b6104036106053660046130b8565b610d36565b6104a2610618366004612fd6565b610f0e565b6105dc61062b366004612edf565b610f5a565b6104b761063e3660046130f6565b610f74565b6104a26106513660046130b8565b610f9c565b610403610664366004612edf565b602b6020525f908152604090205481565b6105dc610683366004612edf565b611012565b61040361069636600461310d565b611020565b6104a26106a9366004612f88565b611270565b6104a26106bc36600461310d565b611312565b610403601c5481565b6106f26106d8366004612edf565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161040d565b60185461047f90610100900460ff1681565b601b546104b7906001600160a01b031681565b6004546104b7906001600160a01b031681565b60395461047f9060ff1681565b61040361075d366004612edf565b60146020525f908152604090205481565b61047f61077c366004612edf565b602d6020525f908152604090205460ff1681565b6015546104b7906001600160a01b031681565b61040360075481565b6107bf6107ba36600461316d565b6113b4565b60405161040d939291906131b4565b6025546104b7906001600160a01b031681565b6037546106f2906001600160601b031681565b6020546104b7906001600160a01b031681565b61083e610815366004612edf565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161040d565b6002546104b7906001600160a01b031681565b610403610883366004612edf565b602a6020525f908152604090205481565b6104036108a2366004612f88565b611461565b61040360175481565b6033546001600160a01b03166104b7565b6108d66a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b03909116815260200161040d565b6021546104b7906001600160a01b031681565b6031546104b7906001600160a01b031681565b61040361092236600461310d565b6114ad565b6026546104b7906001600160a01b031681565b6106f25f81565b61040361094f3660046130b8565b611626565b6104b76109623660046131dd565b611995565b6003546104b7906001600160a01b031681565b61047f610988366004612edf565b60386020525f908152604090205460ff1681565b61083e6109aa366004612edf565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61047f6109e1366004613207565b6119c9565b61040360055481565b6104036109fd3660046130b8565b611a0d565b6104a2610a1036600461327e565b611a59565b61047f610a23366004612efa565b603260209081525f928352604080842090915290825290205460ff1681565b5f546104b7906001600160a01b031681565b610403601a5481565b6031546001600160a01b031615610ace576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610aa09086908990600401613311565b5f604051808303815f87803b158015610ab7575f80fd5b505af1158015610ac9573d5f803e3d5ffd5b505050505b5050505050565b5f610ade611b4e565b610ae9856003611b9e565b610afa610af586611bec565b611c0e565b5f6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b66919061332b565b90529050610b748682611c56565b610b7f868583611ded565b5f9150505b949350505050565b6031546001600160a01b031615610bfd576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610bcf9086908890600401613311565b5f604051808303815f87803b158015610be6575f80fd5b505af1158015610bf8573d5f803e3d5ffd5b505050505b50505050565b6031546001600160a01b031615610cd3576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610c469086908a90600401613311565b5f604051808303815f87803b158015610c5d575f80fd5b505af1158015610c6f573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610ca59087908a90600401613311565b5f604051808303815f87803b158015610cbc575f80fd5b505af1158015610cce573d5f803e3d5ffd5b505050505b505050505050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b5f805f805f80610d0f8a8a8a8a5f611f71565b925092509250826014811115610d2757610d27613342565b9a919950975095505050505050565b5f610d3f611b4e565b610d49845f611b9e565b610d55610af585611bec565b6001600160a01b0384165f9081526027602052604081205490819003610dbb5760405162461bcd60e51b815260206004820152601660248201527506d61726b657420737570706c792063617020697320360541b60448201526064015b60405180910390fd5b5f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1c919061332b565b90505f6040518060200160405280886001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e66573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8a919061332b565b905290505f610e9a82848861201e565b905083811115610eec5760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420737570706c79206361702072656163686564000000000000006044820152606401610db2565b610ef58861203e565b610eff88886121ab565b5f9450505050505b9392505050565b80151580610f1a575081155b610b8c5760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610db2565b5f805f610f67845f612349565b9250925092509193909250565b600d8181548110610f83575f80fd5b5f918252602090912001546001600160a01b0316905081565b6031546001600160a01b03161561100d576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610fdf9085908790600401613311565b5f604051808303815f87803b158015610ff6575f80fd5b505af1158015611008573d5f803e3d5ffd5b505050505b505050565b5f805f610f67846001612349565b5f611029611b4e565b611034866005611b9e565b6025546001600160a01b03161580159061105c57506025546001600160a01b03858116911614155b1561106957506001611267565b611075610af586611bec565b6015545f906001600160a01b0388811691161461110757611098610af588611bec565b6040516395dd919360e01b81526001600160a01b0385811660048301528816906395dd919390602401602060405180830381865afa1580156110dc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611100919061332b565b9050611176565b601554604051633c617c9160e11b81526001600160a01b038681166004830152909116906378c2f92290602401602060405180830381865afa15801561114f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611173919061332b565b90505b6001600160a01b0387165f908152602d602052604090205460ff16806111c057506001600160a01b038085165f908152603260209081526040808320938b168352929052205460ff165b156111de57808311156111d85760115b915050611267565b5f6111d0565b5f806111ee865f805f6001611f71565b9193509091505f905082601481111561120957611209613342565b1461122a5781601481111561122057611220613342565b9350505050611267565b805f03611238576003611220565b611252604051806020016040528060055481525084612381565b851115611260576011611220565b5f93505050505b95945050505050565b6031546001600160a01b031615610bfd576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906112b39086908890600401613311565b5f604051808303815f87803b1580156112ca575f80fd5b505af11580156112dc573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610bcf9085908890600401613311565b6031546001600160a01b031615610ace576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906113559085908990600401613311565b5f604051808303815f87803b15801561136c575f80fd5b505af115801561137e573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610aa09086908990600401613311565b60366020525f90815260409020805481906113ce90613356565b80601f01602080910402602001604051908101604052809291908181526020018280546113fa90613356565b80156114455780601f1061141c57610100808354040283529160200191611445565b820191905f5260205f20905b81548152906001019060200180831161142857829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f61146a611b4e565b611475856006611b9e565b5f611481868685612398565b90508015611490579050610b84565b6114998661203e565b6114a386866121ab565b610b7f86856121ab565b5f6114b6611b4e565b6114c1866004611b9e565b5f6114cb87611bec565b90506114d681611c0e565b6001600160a01b0384165f90815260028201602052604090205460ff166114fe5760136111d0565b6015546001600160a01b0387811691161461151f5761151f610af587611bec565b856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561155b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157f919061338e565b6001600160a01b0316876001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e8919061338e565b6001600160a01b0316146115fd5760026111d0565b6116068761203e565b61161087856121ab565b61161a87866121ab565b5f979650505050505050565b5f61162f611b4e565b61163a846002611b9e565b611646610af585611bec565b6116508385612431565b6001600160a01b0384165f908152601f6020526040812054908190036116b15760405162461bcd60e51b815260206004820152601660248201527506d61726b657420626f72726f772063617020697320360541b6044820152606401610db2565b6116ba85611bec565b6001600160a01b0385165f908152600291909101602052604090205460ff1661176f57336001600160a01b0386161461172d5760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba103132903b2a37b5b2b760591b6044820152606401610db2565b5f61173886866124f4565b90505f81601481111561174d5761174d613342565b1461176d5780601481111561176457611764613342565b92505050610f07565b505b6004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa1580156117b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117dd919061332b565b5f036117ed57600d915050610f07565b5f611857866001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561182d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611851919061332b565b856125c7565b9050818111156118a95760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610db2565b5f806118b887895f895f611f71565b9193509091505f90508260148111156118d3576118d3613342565b146118f5578160148111156118ea576118ea613342565b945050505050610f07565b80156119025760046118ea565b5f60405180602001604052808a6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561194a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196e919061332b565b9052905061197c8982611c56565b611987898983611ded565b5f9998505050505050505050565b6008602052815f5260405f2081815481106119ae575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f908152602960205260408120818360088111156119f3576119f3613342565b815260208101919091526040015f205460ff169392505050565b5f611a16611b4e565b611a21846001611b9e565b5f611a2d858585612398565b90508015611a3c579050610f07565b611a458561203e565b611a4f85856121ab565b5f95945050505050565b611a616125fc565b848381148015611a7057508082145b611aac5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610db2565b5f5b81811015610bf857611ae5888883818110611acb57611acb6133a9565b9050602002016020810190611ae09190612edf565b612646565b611b46888883818110611afa57611afa6133a9565b9050602002016020810190611b0f9190612edf565b878784818110611b2157611b216133a9565b90506020020135868685818110611b3a57611b3a6133a9565b90506020020135612694565b600101611aae565b60185462010000900460ff1615611b9c5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610db2565b565b611ba882826119c9565b15611be85760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610db2565b5050565b5f60095f611bfa5f85610cdb565b81526020019081526020015f209050919050565b805460ff16611c535760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610db2565b50565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611c8261280e565b83549091505f90611ca39063ffffffff80851691600160e01b900416612847565b90508015801590611cb357508215155b15611dc2575f611d22876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d1c919061332b565b87612880565b90505f611d2f838661289d565b90505f825f03611d4d5760405180602001604052805f815250611d57565b611d5782846128de565b604080516020810190915288546001600160e01b03168152909150611da090611d809083612921565b516040805180820190915260038152620c8c8d60ea1b602082015261294a565b6001600160e01b0316600160e01b63ffffffff87160217875550610cd3915050565b8015610cd357835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b601b546001600160a01b031615611e0657611e06612978565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b03909216908190559080158015611e6257506a0c097ce7bc90715b34b9f160241b8210155b15611e7857506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611e8e8585612847565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f91611ee791611ee1918a16906395dd919390602401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b83612aea565b6001600160a01b0387165f90815260146020526040902054909150611f0c90826125c7565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e90611fb79030908f908f908f908f908f906004016133bd565b606060405180830381865afa158015611fd2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ff69190613418565b92509250925082601481111561200e5761200e613342565b9b919a5098509650505050505050565b5f8061202a8585612b11565b905061126761203882612b37565b846125c7565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161206a61280e565b83549091505f9061208b9063ffffffff80851691600160e01b900416612847565b9050801580159061209b57508215155b15612181575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612101919061332b565b90505f61210e838661289d565b90505f825f0361212c5760405180602001604052805f815250612136565b61213682846128de565b604080516020810190915288546001600160e01b0316815290915061215f90611d809083612921565b6001600160e01b0316600160e01b63ffffffff87160217875550610ace915050565b8015610ace57835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b601b546001600160a01b0316156121c4576121c4612978565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b0390921690819055908015801561222057506a0c097ce7bc90715b34b9f160241b8210155b1561223657506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061224c8585612847565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f916122c091908816906370a0823190602401602060405180830381865afa15801561229c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee1919061332b565b6001600160a01b0386165f908152601460205260409020549091506122e590826125c7565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f805f805f8061235c885f805f8b611f71565b92509250925082601481111561237457612374613342565b9891975095509350505050565b5f8061238d8484612b11565b9050610b8481612b37565b5f6123a5610af585611bec565b6123ae84611bec565b6001600160a01b0384165f908152600291909101602052604090205460ff166123d857505f610f07565b5f806123e78587865f80611f71565b9193509091505f905082601481111561240257612402613342565b146124195781601481111561176457611764613342565b8015612426576004611764565b5f9695505050505050565b6001600160a01b0382165f908152603560205260408120546001600160601b03169061245d8284610cdb565b5f81815260096020526040902060060154909150600160601b900460ff16612498576040516305b80c7960e41b815260040160405180910390fd5b6001600160601b038216158015906124cb57506001600160601b0382165f9081526036602052604090206002015460ff16155b15610bfd57604051632da4cc0560e01b81526001600160601b0383166004820152602401610db2565b5f612500836007611b9e565b5f61250a84611bec565b905061251581611c0e565b6001600160a01b0383165f90815260028201602052604090205460ff1615612540575f915050610cf6565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b5f610f078383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612b4e565b5f546001600160a01b03163314611b9c5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610db2565b6001600160a01b038116611c535760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610db2565b6126a0610af584611bec565b6001600160a01b0383165f908152602b6020526040902054821461271c576126c78361203e565b6001600160a01b0383165f818152602b602052604090819020849055517fa9ff26899e4982e7634afa9f70115dcfb61a17d6e8cdd91aa837671d0ff40ba6906127139085815260200190565b60405180910390a25b6001600160a01b0383165f908152602a6020526040902054811461100d575f6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612782573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127a6919061332b565b905290506127b48482611c56565b6001600160a01b0384165f818152602a602052604090819020849055517f0c62c1bc89ec4c40dccb4d21543e782c5ba43897c0075d108d8964181ea3c51b906128009085815260200190565b60405180910390a250505050565b5f6128424360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612b87565b905090565b5f610f078383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612bae565b5f610f0761289684670de0b6b3a764000061289d565b8351612bdc565b5f610f0783836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612c0e565b60408051602081019091525f81526040518060200160405280612918612912866a0c097ce7bc90715b34b9f160241b61289d565b85612bdc565b90529392505050565b60408051602081019091525f81526040518060200160405280612918855f0151855f01516125c7565b5f81600160e01b84106129705760405162461bcd60e51b8152600401610db29190613443565b509192915050565b601c5415806129885750601c5443105b1561298f57565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156129d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129fd919061332b565b9050805f03612a0a575050565b5f80612a1843601c54612847565b90505f612a27601a548361289d565b9050808410612a3857809250612a3c565b8392505b601d54831015612a4d575050505050565b43601c55601b54612a6b906001600160a01b03878116911685612c5e565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ab7575f80fd5b5f6a0c097ce7bc90715b34b9f160241b612b0784845f015161289d565b610f079190613469565b60408051602081019091525f81526040518060200160405280612918855f01518561289d565b80515f90610cf690670de0b6b3a764000090613469565b5f80612b5a8486613488565b90508285821015612b7e5760405162461bcd60e51b8152600401610db29190613443565b50949350505050565b5f8164010000000084106129705760405162461bcd60e51b8152600401610db29190613443565b5f8184841115612bd15760405162461bcd60e51b8152600401610db29190613443565b50610b84838561349b565b5f610f0783836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612cb0565b5f831580612c1a575082155b15612c2657505f610f07565b5f612c3184866134ae565b905083612c3e8683613469565b148390612b7e5760405162461bcd60e51b8152600401610db29190613443565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261100d908490612cdb565b5f8183612cd05760405162461bcd60e51b8152600401610db29190613443565b50610b848385613469565b5f612d2f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612dae9092919063ffffffff16565b905080515f1480612d4f575080806020019051810190612d4f91906134c5565b61100d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610db2565b6060610b8484845f85855f80866001600160a01b03168587604051612dd391906134e4565b5f6040518083038185875af1925050503d805f8114612e0d576040519150601f19603f3d011682016040523d82523d5f602084013e612e12565b606091505b5091509150612e2387838387612e2e565b979650505050505050565b60608315612e9c5782515f03612e95576001600160a01b0385163b612e955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610db2565b5081610b84565b610b848383815115612eb15781518083602001fd5b8060405162461bcd60e51b8152600401610db29190613443565b6001600160a01b0381168114611c53575f80fd5b5f60208284031215612eef575f80fd5b8135610f0781612ecb565b5f8060408385031215612f0b575f80fd5b8235612f1681612ecb565b91506020830135612f2681612ecb565b809150509250929050565b5f805f805f60a08688031215612f45575f80fd5b8535612f5081612ecb565b94506020860135612f6081612ecb565b93506040860135612f7081612ecb565b94979396509394606081013594506080013592915050565b5f805f8060808587031215612f9b575f80fd5b8435612fa681612ecb565b93506020850135612fb681612ecb565b92506040850135612fc681612ecb565b9396929550929360600135925050565b5f805f8060808587031215612fe9575f80fd5b8435612ff481612ecb565b9350602085013561300481612ecb565b93969395505050506040820135916060013590565b5f805f805f8060c0878903121561302e575f80fd5b863561303981612ecb565b9550602087013561304981612ecb565b9450604087013561305981612ecb565b9350606087013561306981612ecb565b9598949750929560808101359460a0909101359350915050565b80356001600160601b0381168114613099575f80fd5b919050565b5f80604083850312156130af575f80fd5b612f1683613083565b5f805f606084860312156130ca575f80fd5b83356130d581612ecb565b925060208401356130e581612ecb565b929592945050506040919091013590565b5f60208284031215613106575f80fd5b5035919050565b5f805f805f60a08688031215613121575f80fd5b853561312c81612ecb565b9450602086013561313c81612ecb565b9350604086013561314c81612ecb565b9250606086013561315c81612ecb565b949793965091946080013592915050565b5f6020828403121561317d575f80fd5b610f0782613083565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6131c66060830186613186565b931515602083015250901515604090910152919050565b5f80604083850312156131ee575f80fd5b82356131f981612ecb565b946020939093013593505050565b5f8060408385031215613218575f80fd5b823561322381612ecb565b9150602083013560098110612f26575f80fd5b5f8083601f840112613246575f80fd5b50813567ffffffffffffffff81111561325d575f80fd5b6020830191508360208260051b8501011115613277575f80fd5b9250929050565b5f805f805f8060608789031215613293575f80fd5b863567ffffffffffffffff808211156132aa575f80fd5b6132b68a838b01613236565b909850965060208901359150808211156132ce575f80fd5b6132da8a838b01613236565b909650945060408901359150808211156132f2575f80fd5b506132ff89828a01613236565b979a9699509497509295939492505050565b6001600160a01b0392831681529116602082015260400190565b5f6020828403121561333b575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c9082168061336a57607f821691505b60208210810361338857634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561339e575f80fd5b8151610f0781612ecb565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c081016002831061340757634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f6060848603121561342a575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610f076020830184613186565b634e487b7160e01b5f52601160045260245ffd5b5f8261348357634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610cf657610cf6613455565b81810381811115610cf657610cf6613455565b8082028115828204841417610cf657610cf6613455565b5f602082840312156134d5575f80fd5b81518015158114610f07575f80fd5b5f82518060208501845e5f92019182525091905056fea26469706673582212207cd5f621d2b69e8b6c5d9a886845faa973f3a67a1195d459753ae549f728168064736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106103e0575f3560e01c80637dc0d1d01161020b578063c5f956af1161011f578063e0f6123d116100b4578063eabe7d9111610084578063eabe7d91146109ef578063ead1a8a014610a02578063f445d70314610a15578063f851a44014610a42578063fa6331d814610a54575f80fd5b8063e0f6123d1461097a578063e37d4b791461099c578063e85a2960146109d3578063e8755446146109e6575f80fd5b8063d463654c116100ef578063d463654c1461093a578063da3d454c14610941578063dce1544914610954578063dcfbc0c714610967575f80fd5b8063c5f956af146108ee578063c7ee005e14610901578063d02f735114610914578063d3270f9914610927575f80fd5b8063a657e579116101a0578063bbb8864a11610170578063bbb8864a14610875578063bdcdc25814610894578063bec04f72146108a7578063bf32442d146108b0578063c5b4db55146108c1575f80fd5b8063a657e579146107e1578063b2eafc39146107f4578063b8324c7c14610807578063bb82aa5e14610862575f80fd5b80639254f5e5116101db5780639254f5e51461079057806394b2294b146107a357806396c99064146107ac5780639bb27d62146107ce575f80fd5b80637dc0d1d01461072f5780637fb8e8cd146107425780638a7dc1651461074f5780638c1ac18a1461076e575f80fd5b80634a584432116103025780635dd3fc9d116102975780636d35bf91116102675780636d35bf91146106ae578063719f701b146106c157806373769099146106ca578063765513831461070a5780637d172bd51461071c575f80fd5b80635dd3fc9d146106565780635ec88c79146106755780635fc7e71e146106885780636a56947e1461069b575f80fd5b806351dff989116102d257806351dff9891461060a578063528a174c1461061d57806352d84d1e146106305780635c77860514610643575f80fd5b80634a584432146105975780634d99c776146105b65780634e79238f146105c95780634ef4c3e1146105f7575f80fd5b806324a3d6221161037857806341a18d2c1161034857806341a18d2c1461053457806341c728b91461055e578063425fad581461057157806347ef3b3b14610584575f80fd5b806324a3d622146104e257806326782247146104f55780632bc7e29e146105085780634088c73e14610527575f80fd5b806310b98338116103b357806310b98338146104525780631ededc911461048f57806321af4569146104a457806324008a62146104cf575f80fd5b806302c3bcbb146103e457806304ef9d581461041657806308e0225c1461041f5780630db4b4e514610449575b5f80fd5b6104036103f2366004612edf565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61040360225481565b61040361042d366004612efa565b601360209081525f928352604080842090915290825290205481565b610403601d5481565b61047f610460366004612efa565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161040d565b6104a261049d366004612f31565b610a5d565b005b601e546104b7906001600160a01b031681565b6040516001600160a01b03909116815260200161040d565b6104036104dd366004612f88565b610ad5565b600a546104b7906001600160a01b031681565b6001546104b7906001600160a01b031681565b610403610516366004612edf565b60166020525f908152604090205481565b60185461047f9060ff1681565b610403610542366004612efa565b601260209081525f928352604080842090915290825290205481565b6104a261056c366004612fd6565b610b8c565b60185461047f9062010000900460ff1681565b6104a2610592366004613019565b610c03565b6104036105a5366004612edf565b601f6020525f908152604090205481565b6104036105c436600461309e565b610cdb565b6105dc6105d7366004612fd6565b610cfc565b6040805193845260208401929092529082015260600161040d565b6104036106053660046130b8565b610d36565b6104a2610618366004612fd6565b610f0e565b6105dc61062b366004612edf565b610f5a565b6104b761063e3660046130f6565b610f74565b6104a26106513660046130b8565b610f9c565b610403610664366004612edf565b602b6020525f908152604090205481565b6105dc610683366004612edf565b611012565b61040361069636600461310d565b611020565b6104a26106a9366004612f88565b611270565b6104a26106bc36600461310d565b611312565b610403601c5481565b6106f26106d8366004612edf565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161040d565b60185461047f90610100900460ff1681565b601b546104b7906001600160a01b031681565b6004546104b7906001600160a01b031681565b60395461047f9060ff1681565b61040361075d366004612edf565b60146020525f908152604090205481565b61047f61077c366004612edf565b602d6020525f908152604090205460ff1681565b6015546104b7906001600160a01b031681565b61040360075481565b6107bf6107ba36600461316d565b6113b4565b60405161040d939291906131b4565b6025546104b7906001600160a01b031681565b6037546106f2906001600160601b031681565b6020546104b7906001600160a01b031681565b61083e610815366004612edf565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161040d565b6002546104b7906001600160a01b031681565b610403610883366004612edf565b602a6020525f908152604090205481565b6104036108a2366004612f88565b611461565b61040360175481565b6033546001600160a01b03166104b7565b6108d66a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b03909116815260200161040d565b6021546104b7906001600160a01b031681565b6031546104b7906001600160a01b031681565b61040361092236600461310d565b6114ad565b6026546104b7906001600160a01b031681565b6106f25f81565b61040361094f3660046130b8565b611626565b6104b76109623660046131dd565b611995565b6003546104b7906001600160a01b031681565b61047f610988366004612edf565b60386020525f908152604090205460ff1681565b61083e6109aa366004612edf565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61047f6109e1366004613207565b6119c9565b61040360055481565b6104036109fd3660046130b8565b611a0d565b6104a2610a1036600461327e565b611a59565b61047f610a23366004612efa565b603260209081525f928352604080842090915290825290205460ff1681565b5f546104b7906001600160a01b031681565b610403601a5481565b6031546001600160a01b031615610ace576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610aa09086908990600401613311565b5f604051808303815f87803b158015610ab7575f80fd5b505af1158015610ac9573d5f803e3d5ffd5b505050505b5050505050565b5f610ade611b4e565b610ae9856003611b9e565b610afa610af586611bec565b611c0e565b5f6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b66919061332b565b90529050610b748682611c56565b610b7f868583611ded565b5f9150505b949350505050565b6031546001600160a01b031615610bfd576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610bcf9086908890600401613311565b5f604051808303815f87803b158015610be6575f80fd5b505af1158015610bf8573d5f803e3d5ffd5b505050505b50505050565b6031546001600160a01b031615610cd3576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610c469086908a90600401613311565b5f604051808303815f87803b158015610c5d575f80fd5b505af1158015610c6f573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610ca59087908a90600401613311565b5f604051808303815f87803b158015610cbc575f80fd5b505af1158015610cce573d5f803e3d5ffd5b505050505b505050505050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b5f805f805f80610d0f8a8a8a8a5f611f71565b925092509250826014811115610d2757610d27613342565b9a919950975095505050505050565b5f610d3f611b4e565b610d49845f611b9e565b610d55610af585611bec565b6001600160a01b0384165f9081526027602052604081205490819003610dbb5760405162461bcd60e51b815260206004820152601660248201527506d61726b657420737570706c792063617020697320360541b60448201526064015b60405180910390fd5b5f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1c919061332b565b90505f6040518060200160405280886001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e66573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8a919061332b565b905290505f610e9a82848861201e565b905083811115610eec5760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420737570706c79206361702072656163686564000000000000006044820152606401610db2565b610ef58861203e565b610eff88886121ab565b5f9450505050505b9392505050565b80151580610f1a575081155b610b8c5760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610db2565b5f805f610f67845f612349565b9250925092509193909250565b600d8181548110610f83575f80fd5b5f918252602090912001546001600160a01b0316905081565b6031546001600160a01b03161561100d576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610fdf9085908790600401613311565b5f604051808303815f87803b158015610ff6575f80fd5b505af1158015611008573d5f803e3d5ffd5b505050505b505050565b5f805f610f67846001612349565b5f611029611b4e565b611034866005611b9e565b6025546001600160a01b03161580159061105c57506025546001600160a01b03858116911614155b1561106957506001611267565b611075610af586611bec565b6015545f906001600160a01b0388811691161461110757611098610af588611bec565b6040516395dd919360e01b81526001600160a01b0385811660048301528816906395dd919390602401602060405180830381865afa1580156110dc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611100919061332b565b9050611176565b601554604051633c617c9160e11b81526001600160a01b038681166004830152909116906378c2f92290602401602060405180830381865afa15801561114f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611173919061332b565b90505b6001600160a01b0387165f908152602d602052604090205460ff16806111c057506001600160a01b038085165f908152603260209081526040808320938b168352929052205460ff165b156111de57808311156111d85760115b915050611267565b5f6111d0565b5f806111ee865f805f6001611f71565b9193509091505f905082601481111561120957611209613342565b1461122a5781601481111561122057611220613342565b9350505050611267565b805f03611238576003611220565b611252604051806020016040528060055481525084612381565b851115611260576011611220565b5f93505050505b95945050505050565b6031546001600160a01b031615610bfd576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906112b39086908890600401613311565b5f604051808303815f87803b1580156112ca575f80fd5b505af11580156112dc573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610bcf9085908890600401613311565b6031546001600160a01b031615610ace576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906113559085908990600401613311565b5f604051808303815f87803b15801561136c575f80fd5b505af115801561137e573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610aa09086908990600401613311565b60366020525f90815260409020805481906113ce90613356565b80601f01602080910402602001604051908101604052809291908181526020018280546113fa90613356565b80156114455780601f1061141c57610100808354040283529160200191611445565b820191905f5260205f20905b81548152906001019060200180831161142857829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f61146a611b4e565b611475856006611b9e565b5f611481868685612398565b90508015611490579050610b84565b6114998661203e565b6114a386866121ab565b610b7f86856121ab565b5f6114b6611b4e565b6114c1866004611b9e565b5f6114cb87611bec565b90506114d681611c0e565b6001600160a01b0384165f90815260028201602052604090205460ff166114fe5760136111d0565b6015546001600160a01b0387811691161461151f5761151f610af587611bec565b856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561155b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157f919061338e565b6001600160a01b0316876001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e8919061338e565b6001600160a01b0316146115fd5760026111d0565b6116068761203e565b61161087856121ab565b61161a87866121ab565b5f979650505050505050565b5f61162f611b4e565b61163a846002611b9e565b611646610af585611bec565b6116508385612431565b6001600160a01b0384165f908152601f6020526040812054908190036116b15760405162461bcd60e51b815260206004820152601660248201527506d61726b657420626f72726f772063617020697320360541b6044820152606401610db2565b6116ba85611bec565b6001600160a01b0385165f908152600291909101602052604090205460ff1661176f57336001600160a01b0386161461172d5760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba103132903b2a37b5b2b760591b6044820152606401610db2565b5f61173886866124f4565b90505f81601481111561174d5761174d613342565b1461176d5780601481111561176457611764613342565b92505050610f07565b505b6004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa1580156117b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117dd919061332b565b5f036117ed57600d915050610f07565b5f611857866001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561182d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611851919061332b565b856125c7565b9050818111156118a95760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610db2565b5f806118b887895f895f611f71565b9193509091505f90508260148111156118d3576118d3613342565b146118f5578160148111156118ea576118ea613342565b945050505050610f07565b80156119025760046118ea565b5f60405180602001604052808a6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561194a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196e919061332b565b9052905061197c8982611c56565b611987898983611ded565b5f9998505050505050505050565b6008602052815f5260405f2081815481106119ae575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f908152602960205260408120818360088111156119f3576119f3613342565b815260208101919091526040015f205460ff169392505050565b5f611a16611b4e565b611a21846001611b9e565b5f611a2d858585612398565b90508015611a3c579050610f07565b611a458561203e565b611a4f85856121ab565b5f95945050505050565b611a616125fc565b848381148015611a7057508082145b611aac5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610db2565b5f5b81811015610bf857611ae5888883818110611acb57611acb6133a9565b9050602002016020810190611ae09190612edf565b612646565b611b46888883818110611afa57611afa6133a9565b9050602002016020810190611b0f9190612edf565b878784818110611b2157611b216133a9565b90506020020135868685818110611b3a57611b3a6133a9565b90506020020135612694565b600101611aae565b60185462010000900460ff1615611b9c5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610db2565b565b611ba882826119c9565b15611be85760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610db2565b5050565b5f60095f611bfa5f85610cdb565b81526020019081526020015f209050919050565b805460ff16611c535760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610db2565b50565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611c8261280e565b83549091505f90611ca39063ffffffff80851691600160e01b900416612847565b90508015801590611cb357508215155b15611dc2575f611d22876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d1c919061332b565b87612880565b90505f611d2f838661289d565b90505f825f03611d4d5760405180602001604052805f815250611d57565b611d5782846128de565b604080516020810190915288546001600160e01b03168152909150611da090611d809083612921565b516040805180820190915260038152620c8c8d60ea1b602082015261294a565b6001600160e01b0316600160e01b63ffffffff87160217875550610cd3915050565b8015610cd357835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b601b546001600160a01b031615611e0657611e06612978565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b03909216908190559080158015611e6257506a0c097ce7bc90715b34b9f160241b8210155b15611e7857506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611e8e8585612847565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f91611ee791611ee1918a16906395dd919390602401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b83612aea565b6001600160a01b0387165f90815260146020526040902054909150611f0c90826125c7565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e90611fb79030908f908f908f908f908f906004016133bd565b606060405180830381865afa158015611fd2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ff69190613418565b92509250925082601481111561200e5761200e613342565b9b919a5098509650505050505050565b5f8061202a8585612b11565b905061126761203882612b37565b846125c7565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161206a61280e565b83549091505f9061208b9063ffffffff80851691600160e01b900416612847565b9050801580159061209b57508215155b15612181575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612101919061332b565b90505f61210e838661289d565b90505f825f0361212c5760405180602001604052805f815250612136565b61213682846128de565b604080516020810190915288546001600160e01b0316815290915061215f90611d809083612921565b6001600160e01b0316600160e01b63ffffffff87160217875550610ace915050565b8015610ace57835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b601b546001600160a01b0316156121c4576121c4612978565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b0390921690819055908015801561222057506a0c097ce7bc90715b34b9f160241b8210155b1561223657506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061224c8585612847565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f916122c091908816906370a0823190602401602060405180830381865afa15801561229c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee1919061332b565b6001600160a01b0386165f908152601460205260409020549091506122e590826125c7565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f805f805f8061235c885f805f8b611f71565b92509250925082601481111561237457612374613342565b9891975095509350505050565b5f8061238d8484612b11565b9050610b8481612b37565b5f6123a5610af585611bec565b6123ae84611bec565b6001600160a01b0384165f908152600291909101602052604090205460ff166123d857505f610f07565b5f806123e78587865f80611f71565b9193509091505f905082601481111561240257612402613342565b146124195781601481111561176457611764613342565b8015612426576004611764565b5f9695505050505050565b6001600160a01b0382165f908152603560205260408120546001600160601b03169061245d8284610cdb565b5f81815260096020526040902060060154909150600160601b900460ff16612498576040516305b80c7960e41b815260040160405180910390fd5b6001600160601b038216158015906124cb57506001600160601b0382165f9081526036602052604090206002015460ff16155b15610bfd57604051632da4cc0560e01b81526001600160601b0383166004820152602401610db2565b5f612500836007611b9e565b5f61250a84611bec565b905061251581611c0e565b6001600160a01b0383165f90815260028201602052604090205460ff1615612540575f915050610cf6565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b5f610f078383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612b4e565b5f546001600160a01b03163314611b9c5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610db2565b6001600160a01b038116611c535760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610db2565b6126a0610af584611bec565b6001600160a01b0383165f908152602b6020526040902054821461271c576126c78361203e565b6001600160a01b0383165f818152602b602052604090819020849055517fa9ff26899e4982e7634afa9f70115dcfb61a17d6e8cdd91aa837671d0ff40ba6906127139085815260200190565b60405180910390a25b6001600160a01b0383165f908152602a6020526040902054811461100d575f6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612782573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127a6919061332b565b905290506127b48482611c56565b6001600160a01b0384165f818152602a602052604090819020849055517f0c62c1bc89ec4c40dccb4d21543e782c5ba43897c0075d108d8964181ea3c51b906128009085815260200190565b60405180910390a250505050565b5f6128424360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612b87565b905090565b5f610f078383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612bae565b5f610f0761289684670de0b6b3a764000061289d565b8351612bdc565b5f610f0783836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612c0e565b60408051602081019091525f81526040518060200160405280612918612912866a0c097ce7bc90715b34b9f160241b61289d565b85612bdc565b90529392505050565b60408051602081019091525f81526040518060200160405280612918855f0151855f01516125c7565b5f81600160e01b84106129705760405162461bcd60e51b8152600401610db29190613443565b509192915050565b601c5415806129885750601c5443105b1561298f57565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156129d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129fd919061332b565b9050805f03612a0a575050565b5f80612a1843601c54612847565b90505f612a27601a548361289d565b9050808410612a3857809250612a3c565b8392505b601d54831015612a4d575050505050565b43601c55601b54612a6b906001600160a01b03878116911685612c5e565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ab7575f80fd5b5f6a0c097ce7bc90715b34b9f160241b612b0784845f015161289d565b610f079190613469565b60408051602081019091525f81526040518060200160405280612918855f01518561289d565b80515f90610cf690670de0b6b3a764000090613469565b5f80612b5a8486613488565b90508285821015612b7e5760405162461bcd60e51b8152600401610db29190613443565b50949350505050565b5f8164010000000084106129705760405162461bcd60e51b8152600401610db29190613443565b5f8184841115612bd15760405162461bcd60e51b8152600401610db29190613443565b50610b84838561349b565b5f610f0783836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612cb0565b5f831580612c1a575082155b15612c2657505f610f07565b5f612c3184866134ae565b905083612c3e8683613469565b148390612b7e5760405162461bcd60e51b8152600401610db29190613443565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261100d908490612cdb565b5f8183612cd05760405162461bcd60e51b8152600401610db29190613443565b50610b848385613469565b5f612d2f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612dae9092919063ffffffff16565b905080515f1480612d4f575080806020019051810190612d4f91906134c5565b61100d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610db2565b6060610b8484845f85855f80866001600160a01b03168587604051612dd391906134e4565b5f6040518083038185875af1925050503d805f8114612e0d576040519150601f19603f3d011682016040523d82523d5f602084013e612e12565b606091505b5091509150612e2387838387612e2e565b979650505050505050565b60608315612e9c5782515f03612e95576001600160a01b0385163b612e955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610db2565b5081610b84565b610b848383815115612eb15781518083602001fd5b8060405162461bcd60e51b8152600401610db29190613443565b6001600160a01b0381168114611c53575f80fd5b5f60208284031215612eef575f80fd5b8135610f0781612ecb565b5f8060408385031215612f0b575f80fd5b8235612f1681612ecb565b91506020830135612f2681612ecb565b809150509250929050565b5f805f805f60a08688031215612f45575f80fd5b8535612f5081612ecb565b94506020860135612f6081612ecb565b93506040860135612f7081612ecb565b94979396509394606081013594506080013592915050565b5f805f8060808587031215612f9b575f80fd5b8435612fa681612ecb565b93506020850135612fb681612ecb565b92506040850135612fc681612ecb565b9396929550929360600135925050565b5f805f8060808587031215612fe9575f80fd5b8435612ff481612ecb565b9350602085013561300481612ecb565b93969395505050506040820135916060013590565b5f805f805f8060c0878903121561302e575f80fd5b863561303981612ecb565b9550602087013561304981612ecb565b9450604087013561305981612ecb565b9350606087013561306981612ecb565b9598949750929560808101359460a0909101359350915050565b80356001600160601b0381168114613099575f80fd5b919050565b5f80604083850312156130af575f80fd5b612f1683613083565b5f805f606084860312156130ca575f80fd5b83356130d581612ecb565b925060208401356130e581612ecb565b929592945050506040919091013590565b5f60208284031215613106575f80fd5b5035919050565b5f805f805f60a08688031215613121575f80fd5b853561312c81612ecb565b9450602086013561313c81612ecb565b9350604086013561314c81612ecb565b9250606086013561315c81612ecb565b949793965091946080013592915050565b5f6020828403121561317d575f80fd5b610f0782613083565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6131c66060830186613186565b931515602083015250901515604090910152919050565b5f80604083850312156131ee575f80fd5b82356131f981612ecb565b946020939093013593505050565b5f8060408385031215613218575f80fd5b823561322381612ecb565b9150602083013560098110612f26575f80fd5b5f8083601f840112613246575f80fd5b50813567ffffffffffffffff81111561325d575f80fd5b6020830191508360208260051b8501011115613277575f80fd5b9250929050565b5f805f805f8060608789031215613293575f80fd5b863567ffffffffffffffff808211156132aa575f80fd5b6132b68a838b01613236565b909850965060208901359150808211156132ce575f80fd5b6132da8a838b01613236565b909650945060408901359150808211156132f2575f80fd5b506132ff89828a01613236565b979a9699509497509295939492505050565b6001600160a01b0392831681529116602082015260400190565b5f6020828403121561333b575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c9082168061336a57607f821691505b60208210810361338857634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561339e575f80fd5b8151610f0781612ecb565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c081016002831061340757634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f6060848603121561342a575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610f076020830184613186565b634e487b7160e01b5f52601160045260245ffd5b5f8261348357634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610cf657610cf6613455565b81810381811115610cf657610cf6613455565b8082028115828204841417610cf657610cf6613455565b5f602082840312156134d5575f80fd5b81518015158114610f07575f80fd5b5f82518060208501845e5f92019182525091905056fea26469706673582212207cd5f621d2b69e8b6c5d9a886845faa973f3a67a1195d459753ae549f728168064736f6c63430008190033", + "numDeployments": 6, + "solcInputHash": "cbc4287e135101fe4c78448d0f5f2ecc", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"VenusBorrowSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"VenusSupplySpeedUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"supplySpeeds\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"borrowSpeeds\",\"type\":\"uint256[]\"}],\"name\":\"_setVenusSpeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getBorrowingPower\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the hooks used while transferring the assets\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setVenusSpeeds(address[],uint256[],uint256[])\":{\"details\":\"Allows the contract admin to set XVS speed for a market\",\"params\":{\"borrowSpeeds\":\"New XVS speed for borrow\",\"supplySpeeds\":\"New XVS speed for supply\",\"vTokens\":\"The market whose XVS speed to update\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"vToken\":\"The market to verify the borrow against\"},\"returns\":{\"_0\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"vToken\":\"Asset whose underlying is being borrowed\"}},\"getAccountLiquidity(address)\":{\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), account liquidity in excess of liquidation threshold requirements, account shortfall below liquidation threshold requirements)\"}},\"getBorrowingPower(address)\":{\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"}},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\",\"vTokenModify\":\"The market to hypothetically redeem/borrow in\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The amount of collateral token that will be seized\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"mintAllowed(address,address,uint256)\":{\"params\":{\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\",\"vToken\":\"The market to verify the mint against\"},\"returns\":{\"_0\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\",\"vToken\":\"Asset being minted\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"redeemTokens\":\"The number of vTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\",\"vToken\":\"The market to verify the redeem against\"},\"returns\":{\"_0\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\",\"vToken\":\"Asset being redeemed\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which borrowed the asset\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\",\"vToken\":\"The market to verify the repay against\"},\"returns\":{\"_0\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"payer\":\"The address repaying the borrow\",\"vToken\":\"Asset being repaid\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"The market to verify the transfer against\"},\"returns\":{\"_0\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"Asset being transferred\"}}},\"title\":\"PolicyFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedBorrowerVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a borrower\"},\"DistributedSupplierVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a supplier\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"VenusBorrowSpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new borrow-side XVS speed is calculated for a market\"},\"VenusSupplySpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new supply-side XVS speed is calculated for a market\"}},\"kind\":\"user\",\"methods\":{\"_setVenusSpeeds(address[],uint256[],uint256[])\":{\"notice\":\"Set XVS speed for a single market\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt liquidation threshold requirements\"},\"getBorrowingPower(address)\":{\"notice\":\"Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains all the external pre-hook functions related to vToken\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/PolicyFacet.sol\":\"PolicyFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\\n enum KeeperAction {\\n SetMinPrice,\\n SetMaxPrice,\\n ExitProtectionMode\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool cachingEnabled;\\n }\\n\\n /// @notice One item in an syncPriceBoundsAndProtections payload\\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\\n struct KeeperActionItem {\\n address asset;\\n KeeperAction action;\\n uint256 value;\\n }\\n\\n /// @notice One item in a setTokenConfigs payload\\n struct TokenConfigInput {\\n /// @notice The underlying asset address\\n address asset;\\n /// @notice Minimum time protection stays active after the last trigger (seconds)\\n uint64 cooldownPeriod;\\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\\n uint256 triggerThreshold;\\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\\n uint256 resetThreshold;\\n /// @notice Whether to enable bounded pricing immediately upon initialization\\n bool enableBoundedPricing;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool enableCaching;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n /// @notice Emitted when the per-asset transient caching flag is toggled\\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\\n error InvalidKeeperAction(uint8 action);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage. The transient\\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n /**\\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\\n * Empty `actions` is a no-op success.\\n * @param actions The list of keeper actions to apply\\n * @custom:access Only authorized keeper addresses\\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\\n */\\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param tokenConfig_ Token config input for the asset\\n * @custom:access Only Governance\\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param tokenConfigs_ Array of token config inputs, one per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if the input array is empty\\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\\n * @custom:error VAINotAllowed if any asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n /**\\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\\n * live spot instead of reading or writing the transient slots. The initial value is\\n * set via the `enableCaching` argument of `setTokenConfig`.\\n * @param asset The underlying asset address\\n * @param enabled Whether transient caching is enabled for this asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CachingEnabledUpdated\\n */\\n function setCachingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold,\\n bool cachingEnabled\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0xe223d88c17c0d752fdb33fa223b63ce124a798512f3d69f3800e9508e7dff931\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/PolicyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IPolicyFacet } from \\\"../interfaces/IPolicyFacet.sol\\\";\\n\\nimport { XVSRewardsHelper } from \\\"./XVSRewardsHelper.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title PolicyFacet\\n * @author Venus\\n * @dev This facet contains all the hooks used while transferring the assets\\n * @notice This facet contract contains all the external pre-hook functions related to vToken\\n */\\ncontract PolicyFacet is IPolicyFacet, XVSRewardsHelper {\\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.MINT);\\n ensureListed(getCorePoolMarket(vToken));\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n require(supplyCap != 0, \\\"market supply cap is 0\\\");\\n\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n require(nextTotalSupply <= supplyCap, \\\"market supply cap reached\\\");\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, minter);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n // solhint-disable-next-line no-unused-vars\\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(minter, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.REDEEM);\\n\\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\\n if (allowed != uint256(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, redeemer);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\\n require(redeemTokens != 0 || redeemAmount == 0, \\\"redeemTokens zero\\\");\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.BORROW);\\n ensureListed(getCorePoolMarket(vToken));\\n poolBorrowAllowed(borrower, vToken);\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n require(borrowCap != 0, \\\"market borrow cap is 0\\\");\\n\\n if (!getCorePoolMarket(vToken).accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == vToken, \\\"sender must be vToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(VToken(vToken), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n }\\n\\n (uint256 collateralPrice, uint256 debtPrice) = deviationBoundedOracle.getBoundedPricesView(vToken);\\n if (collateralPrice == 0 || debtPrice == 0) {\\n return uint256(Error.PRICE_ERROR);\\n }\\n\\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\\n require(nextTotalBorrows <= borrowCap, \\\"market borrow cap reached\\\");\\n\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n updateVenusBorrowIndex(vToken, borrowIndex);\\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n // solhint-disable-next-line no-unused-vars\\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address vToken,\\n address payer, // solhint-disable-line no-unused-vars\\n address borrower,\\n uint256 repayAmount // solhint-disable-line no-unused-vars\\n ) external returns (uint256) {\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.REPAY);\\n ensureListed(getCorePoolMarket(vToken));\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n updateVenusBorrowIndex(vToken, borrowIndex);\\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address vToken,\\n address payer, // solhint-disable-line no-unused-vars\\n address borrower,\\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount\\n ) external view returns (uint256) {\\n checkProtocolPauseState();\\n\\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\\n return uint256(Error.UNAUTHORIZED);\\n }\\n\\n ensureListed(getCorePoolMarket(vTokenCollateral));\\n uint256 borrowBalance;\\n if (address(vTokenBorrowed) != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n } else {\\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\\n }\\n\\n if (isForcedLiquidationEnabled[vTokenBorrowed] || isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n return uint(Error.TOO_MUCH_REPAY);\\n }\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\\n borrower,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_LIQUIDATION_THRESHOLD\\n );\\n\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall == 0) {\\n return uint256(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n // The liquidator may not repay more than what is allowed by the closeFactor\\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\\n return uint256(Error.TOO_MUCH_REPAY);\\n }\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n * @param seizeTokens The amount of collateral token that will be seized\\n */\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral, // solhint-disable-line no-unused-vars\\n address liquidator,\\n address borrower,\\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = getCorePoolMarket(vTokenCollateral);\\n\\n // We've added VAIController as a borrowed token list check for seize\\n ensureListed(market);\\n\\n if (!market.accountMembership[borrower]) {\\n return uint256(Error.MARKET_NOT_COLLATERAL);\\n }\\n\\n if (address(vTokenBorrowed) != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n\\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\\n return uint256(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vTokenCollateral);\\n distributeSupplierVenus(vTokenCollateral, borrower);\\n distributeSupplierVenus(vTokenCollateral, liquidator);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\\n if (allowed != uint256(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, src);\\n distributeSupplierVenus(vToken, dst);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n */\\n // solhint-disable-next-line no-unused-vars\\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(src, vToken);\\n prime.accrueInterestAndUpdateScore(dst, vToken);\\n }\\n }\\n\\n /**\\n * @notice Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\\n * @param account The account get liquidity for\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n return (uint256(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt liquidation threshold requirements\\n * @param account The account get liquidity for\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of liquidation threshold requirements,\\n * account shortfall below liquidation threshold requirements)\\n */\\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_LIQUIDATION_THRESHOLD\\n );\\n return (uint256(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n return (uint256(err), liquidity, shortfall);\\n }\\n\\n // setter functionality\\n /**\\n * @notice Set XVS speed for a single market\\n * @dev Allows the contract admin to set XVS speed for a market\\n * @param vTokens The market whose XVS speed to update\\n * @param supplySpeeds New XVS speed for supply\\n * @param borrowSpeeds New XVS speed for borrow\\n */\\n function _setVenusSpeeds(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplySpeeds,\\n uint256[] calldata borrowSpeeds\\n ) external {\\n ensureAdmin();\\n\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n ensureNonzeroAddress(address(vTokens[i]));\\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @dev Internal function to set XVS speed for a single market\\n * @param vToken The market whose XVS speed to update\\n * @param supplySpeed New XVS speed for supply\\n * @param borrowSpeed New XVS speed for borrow\\n * @custom:event VenusSupplySpeedUpdated Emitted after the venus supply speed for a market is updated\\n * @custom:event VenusBorrowSpeedUpdated Emitted after the venus borrow speed for a market is updated\\n */\\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n ensureListed(getCorePoolMarket(address(vToken)));\\n\\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. XVS accrued properly for the old speed, and\\n // 2. XVS accrued at the new speed starts after this block.\\n\\n updateVenusSupplyIndex(address(vToken));\\n // Update speed and emit event\\n venusSupplySpeeds[address(vToken)] = supplySpeed;\\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. XVS accrued properly for the old speed, and\\n // 2. XVS accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n updateVenusBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @dev Checks if vToken borrowing is allowed in the account's entered pool\\n * Reverts if borrowing is not permitted\\n * @param account The address of the account whose borrow permission is being checked\\n * @param vToken The vToken market to check borrowing status for\\n * @custom:error BorrowNotAllowedInPool Reverts if borrowing is not allowed in the account's entered pool\\n * @custom:error InactivePool Reverts if borrowing in an inactive pool.\\n */\\n function poolBorrowAllowed(address account, address vToken) internal view {\\n uint96 userPool = userPoolId[account];\\n PoolMarketId index = getPoolMarketIndex(userPool, vToken);\\n if (!_poolMarkets[index].isBorrowAllowed) {\\n revert BorrowNotAllowedInPool();\\n }\\n if (userPool != corePoolId && !pools[userPool].isActive) {\\n revert InactivePool(userPool);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3d9e8e3929dd3766ce852b5fafd553a03bf086071987bc8501f474cd575d757f\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\n\\n/**\\n * @title XVSRewardsHelper\\n * @author Venus\\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\\n */\\ncontract XVSRewardsHelper is FacetBase {\\n /// @notice Emitted when XVS is distributed to a borrower\\n event DistributedBorrowerVenus(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 venusDelta,\\n uint256 venusBorrowIndex\\n );\\n\\n /// @notice Emitted when XVS is distributed to a supplier\\n event DistributedSupplierVenus(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 venusDelta,\\n uint256 venusSupplyIndex\\n );\\n\\n /**\\n * @notice Accrue XVS to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n */\\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\\n if (deltaBlocks != 0 && borrowSpeed != 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \\\"224\\\");\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n borrowState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Accrue XVS to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n */\\n function updateVenusSupplyIndex(address vToken) internal {\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n uint256 supplySpeed = venusSupplySpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\\n if (deltaBlocks != 0 && supplySpeed != 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \\\"224\\\");\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n supplyState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute XVS to\\n */\\n function distributeSupplierVenus(address vToken, address supplier) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 supplyIndex = venusSupplyState[vToken].index;\\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\\n // Update supplier's index to the current index since we are distributing accrued XVS\\n venusSupplierIndex[vToken][supplier] = supplyIndex;\\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n // Multiply of supplierTokens and supplierDelta\\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\\n // Addition of supplierAccrued and supplierDelta\\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute XVS to\\n */\\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 borrowIndex = venusBorrowState[vToken].index;\\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\\n // Update borrowers's index to the current index since we are distributing accrued XVS\\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0xf356db714f7aada286380ee5092b0a3e3163428943cfb5561ded76597e1c0c15\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IPolicyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IPolicyFacet {\\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\\n\\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\\n\\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\\n\\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) external returns (uint256);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint256 repayAmount,\\n uint256 borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount\\n ) external view returns (uint256);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n uint256 seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external returns (uint256);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external;\\n\\n function transferAllowed(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external returns (uint256);\\n\\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\\n\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256, uint256, uint256);\\n\\n function _setVenusSpeeds(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplySpeeds,\\n uint256[] calldata borrowSpeeds\\n ) external;\\n\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall);\\n}\\n\",\"keccak256\":\"0x6fd69f4b22548e9288f7c025d501966ae4f83132693a8e33f1e35ed55151d111\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b506136f58061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106103eb575f3560e01c80637fb8e8cd1161020b578063c7ee005e1161011f578063e0f6123d116100b4578063eabe7d9111610084578063eabe7d9114610a12578063ead1a8a014610a25578063f445d70314610a38578063f851a44014610a65578063fa6331d814610a77575f80fd5b8063e0f6123d1461099d578063e37d4b79146109bf578063e85a2960146109f6578063e875544614610a09575f80fd5b8063d7c46d2d116100ef578063d7c46d2d1461094c578063da3d454c14610964578063dce1544914610977578063dcfbc0c71461098a575f80fd5b8063c7ee005e1461090c578063d02f73511461091f578063d3270f9914610932578063d463654c14610945575f80fd5b8063b2eafc39116101a0578063bdcdc25811610170578063bdcdc2581461089f578063bec04f72146108b2578063bf32442d146108bb578063c5b4db55146108cc578063c5f956af146108f9575f80fd5b8063b2eafc39146107ff578063b8324c7c14610812578063bb82aa5e1461086d578063bbb8864a14610880575f80fd5b806394b2294b116101db57806394b2294b146107ae57806396c99064146107b75780639bb27d62146107d9578063a657e579146107ec575f80fd5b80637fb8e8cd1461074d5780638a7dc1651461075a5780638c1ac18a146107795780639254f5e51461079b575f80fd5b80634d99c776116103025780635ec88c7911610297578063719f701b11610267578063719f701b146106cc57806373769099146106d557806376551383146107155780637d172bd5146107275780637dc0d1d01461073a575f80fd5b80635ec88c79146106805780635fc7e71e146106935780636a56947e146106a65780636d35bf91146106b9575f80fd5b8063528a174c116102d2578063528a174c1461062857806352d84d1e1461063b5780635c7786051461064e5780635dd3fc9d14610661575f80fd5b80634d99c776146105c15780634e79238f146105d45780634ef4c3e11461060257806351dff98914610615575f80fd5b806324a3d6221161038357806341a18d2c1161035357806341a18d2c1461053f57806341c728b914610569578063425fad581461057c57806347ef3b3b1461058f5780634a584432146105a2575f80fd5b806324a3d622146104ed57806326782247146105005780632bc7e29e146105135780634088c73e14610532575f80fd5b806310b98338116103be57806310b983381461045d5780631ededc911461049a57806321af4569146104af57806324008a62146104da575f80fd5b806302c3bcbb146103ef57806304ef9d581461042157806308e0225c1461042a5780630db4b4e514610454575b5f80fd5b61040e6103fd366004613082565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61040e60225481565b61040e61043836600461309d565b601360209081525f928352604080842090915290825290205481565b61040e601d5481565b61048a61046b36600461309d565b602c60209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610418565b6104ad6104a83660046130d4565b610a80565b005b601e546104c2906001600160a01b031681565b6040516001600160a01b039091168152602001610418565b61040e6104e836600461312b565b610af8565b600a546104c2906001600160a01b031681565b6001546104c2906001600160a01b031681565b61040e610521366004613082565b60166020525f908152604090205481565b60185461048a9060ff1681565b61040e61054d36600461309d565b601260209081525f928352604080842090915290825290205481565b6104ad610577366004613179565b610baf565b60185461048a9062010000900460ff1681565b6104ad61059d3660046131bc565b610c26565b61040e6105b0366004613082565b601f6020525f908152604090205481565b61040e6105cf366004613241565b610cfe565b6105e76105e2366004613179565b610d1f565b60408051938452602084019290925290820152606001610418565b61040e61061036600461325b565b610d59565b6104ad610623366004613179565b610f31565b6105e7610636366004613082565b610f7d565b6104c2610649366004613299565b610fb4565b6104ad61065c36600461325b565b610fdc565b61040e61066f366004613082565b602b6020525f908152604090205481565b6105e761068e366004613082565b611052565b61040e6106a13660046132b0565b611066565b6104ad6106b436600461312b565b6112b6565b6104ad6106c73660046132b0565b611358565b61040e601c5481565b6106fd6106e3366004613082565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610418565b60185461048a90610100900460ff1681565b601b546104c2906001600160a01b031681565b6004546104c2906001600160a01b031681565b60395461048a9060ff1681565b61040e610768366004613082565b60146020525f908152604090205481565b61048a610787366004613082565b602d6020525f908152604090205460ff1681565b6015546104c2906001600160a01b031681565b61040e60075481565b6107ca6107c5366004613310565b6113fa565b60405161041893929190613357565b6025546104c2906001600160a01b031681565b6037546106fd906001600160601b031681565b6020546104c2906001600160a01b031681565b610849610820366004613082565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610418565b6002546104c2906001600160a01b031681565b61040e61088e366004613082565b602a6020525f908152604090205481565b61040e6108ad36600461312b565b6114a7565b61040e60175481565b6033546001600160a01b03166104c2565b6108e16a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b039091168152602001610418565b6021546104c2906001600160a01b031681565b6031546104c2906001600160a01b031681565b61040e61092d3660046132b0565b6114f3565b6026546104c2906001600160a01b031681565b6106fd5f81565b6039546104c29061010090046001600160a01b031681565b61040e61097236600461325b565b61166c565b6104c2610985366004613380565b6119f7565b6003546104c2906001600160a01b031681565b61048a6109ab366004613082565b60386020525f908152604090205460ff1681565b6108496109cd366004613082565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61048a610a043660046133aa565b611a2b565b61040e60055481565b61040e610a2036600461325b565b611a6f565b6104ad610a33366004613421565b611abb565b61048a610a4636600461309d565b603260209081525f928352604080842090915290825290205460ff1681565b5f546104c2906001600160a01b031681565b61040e601a5481565b6031546001600160a01b031615610af1576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610ac390869089906004016134b4565b5f604051808303815f87803b158015610ada575f80fd5b505af1158015610aec573d5f803e3d5ffd5b505050505b5050505050565b5f610b01611bb0565b610b0c856003611c00565b610b1d610b1886611c4e565b611c70565b5f6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b8991906134ce565b90529050610b978682611cb8565b610ba2868583611e4f565b5f9150505b949350505050565b6031546001600160a01b031615610c20576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610bf290869088906004016134b4565b5f604051808303815f87803b158015610c09575f80fd5b505af1158015610c1b573d5f803e3d5ffd5b505050505b50505050565b6031546001600160a01b031615610cf6576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610c699086908a906004016134b4565b5f604051808303815f87803b158015610c80575f80fd5b505af1158015610c92573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610cc89087908a906004016134b4565b5f604051808303815f87803b158015610cdf575f80fd5b505af1158015610cf1573d5f803e3d5ffd5b505050505b505050505050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b5f805f805f80610d328a8a8a8a5f611fd3565b925092509250826014811115610d4a57610d4a6134e5565b9a919950975095505050505050565b5f610d62611bb0565b610d6c845f611c00565b610d78610b1885611c4e565b6001600160a01b0384165f9081526027602052604081205490819003610dde5760405162461bcd60e51b815260206004820152601660248201527506d61726b657420737570706c792063617020697320360541b60448201526064015b60405180910390fd5b5f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3f91906134ce565b90505f6040518060200160405280886001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ead91906134ce565b905290505f610ebd828488612080565b905083811115610f0f5760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420737570706c79206361702072656163686564000000000000006044820152606401610dd5565b610f18886120a0565b610f22888861220d565b5f9450505050505b9392505050565b80151580610f3d575081155b610baf5760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610dd5565b5f805f805f80610f90875f805f80611fd3565b925092509250826014811115610fa857610fa86134e5565b97919650945092505050565b600d8181548110610fc3575f80fd5b5f918252602090912001546001600160a01b0316905081565b6031546001600160a01b03161561104d576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d169061101f90859087906004016134b4565b5f604051808303815f87803b158015611036575f80fd5b505af1158015611048573d5f803e3d5ffd5b505050505b505050565b5f805f805f80610f90875f805f6001611fd3565b5f61106f611bb0565b61107a866005611c00565b6025546001600160a01b0316158015906110a257506025546001600160a01b03858116911614155b156110af575060016112ad565b6110bb610b1886611c4e565b6015545f906001600160a01b0388811691161461114d576110de610b1888611c4e565b6040516395dd919360e01b81526001600160a01b0385811660048301528816906395dd919390602401602060405180830381865afa158015611122573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061114691906134ce565b90506111bc565b601554604051633c617c9160e11b81526001600160a01b038681166004830152909116906378c2f92290602401602060405180830381865afa158015611195573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111b991906134ce565b90505b6001600160a01b0387165f908152602d602052604090205460ff168061120657506001600160a01b038085165f908152603260209081526040808320938b168352929052205460ff165b15611224578083111561121e5760115b9150506112ad565b5f611216565b5f80611234865f805f6001611fd3565b9193509091505f905082601481111561124f5761124f6134e5565b1461127057816014811115611266576112666134e5565b93505050506112ad565b805f0361127e576003611266565b6112986040518060200160405280600554815250846123ab565b8511156112a6576011611266565b5f93505050505b95945050505050565b6031546001600160a01b031615610c20576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906112f990869088906004016134b4565b5f604051808303815f87803b158015611310575f80fd5b505af1158015611322573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610bf290859088906004016134b4565b6031546001600160a01b031615610af1576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d169061139b90859089906004016134b4565b5f604051808303815f87803b1580156113b2575f80fd5b505af11580156113c4573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610ac390869089906004016134b4565b60366020525f9081526040902080548190611414906134f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611440906134f9565b801561148b5780601f106114625761010080835404028352916020019161148b565b820191905f5260205f20905b81548152906001019060200180831161146e57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6114b0611bb0565b6114bb856006611c00565b5f6114c78686856123c2565b905080156114d6579050610ba7565b6114df866120a0565b6114e9868661220d565b610ba2868561220d565b5f6114fc611bb0565b611507866004611c00565b5f61151187611c4e565b905061151c81611c70565b6001600160a01b0384165f90815260028201602052604090205460ff16611544576013611216565b6015546001600160a01b0387811691161461156557611565610b1887611c4e565b856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115c59190613531565b6001600160a01b0316876001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561160a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061162e9190613531565b6001600160a01b031614611643576002611216565b61164c876120a0565b611656878561220d565b611660878661220d565b5f979650505050505050565b5f611675611bb0565b611680846002611c00565b61168c610b1885611c4e565b611696838561245b565b6001600160a01b0384165f908152601f6020526040812054908190036116f75760405162461bcd60e51b815260206004820152601660248201527506d61726b657420626f72726f772063617020697320360541b6044820152606401610dd5565b61170085611c4e565b6001600160a01b0385165f908152600291909101602052604090205460ff166117b557336001600160a01b038616146117735760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba103132903b2a37b5b2b760591b6044820152606401610dd5565b5f61177e868661251e565b90505f816014811115611793576117936134e5565b146117b3578060148111156117aa576117aa6134e5565b92505050610f2a565b505b6039546040516388142b6b60e01b81526001600160a01b0387811660048301525f928392610100909104909116906388142b6b906024016040805180830381865afa158015611806573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061182a919061354c565b91509150815f148061183a575080155b1561184b57600d9350505050610f2a565b5f6118b5886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561188b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118af91906134ce565b876125f1565b9050838111156119075760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610dd5565b5f80611916898b5f8b5f612626565b9193509091505f9050826014811115611931576119316134e5565b1461195557816014811115611948576119486134e5565b9650505050505050610f2a565b8015611962576004611948565b5f60405180602001604052808c6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ce91906134ce565b905290506119dc8b82611cb8565b6119e78b8b83611e4f565b5f9b9a5050505050505050505050565b6008602052815f5260405f208181548110611a10575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611a5557611a556134e5565b815260208101919091526040015f205460ff169392505050565b5f611a78611bb0565b611a83846001611c00565b5f611a8f8585856123c2565b90508015611a9e579050610f2a565b611aa7856120a0565b611ab1858561220d565b5f95945050505050565b611ac3612688565b848381148015611ad257508082145b611b0e5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610dd5565b5f5b81811015610c1b57611b47888883818110611b2d57611b2d61356e565b9050602002016020810190611b429190613082565b6126d2565b611ba8888883818110611b5c57611b5c61356e565b9050602002016020810190611b719190613082565b878784818110611b8357611b8361356e565b90506020020135868685818110611b9c57611b9c61356e565b90506020020135612720565b600101611b10565b60185462010000900460ff1615611bfe5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610dd5565b565b611c0a8282611a2b565b15611c4a5760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610dd5565b5050565b5f60095f611c5c5f85610cfe565b81526020019081526020015f209050919050565b805460ff16611cb55760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610dd5565b50565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611ce461289a565b83549091505f90611d059063ffffffff80851691600160e01b9004166128d3565b90508015801590611d1557508215155b15611e24575f611d84876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d7e91906134ce565b8761290c565b90505f611d918386612929565b90505f825f03611daf5760405180602001604052805f815250611db9565b611db9828461296a565b604080516020810190915288546001600160e01b03168152909150611e0290611de290836129ad565b516040805180820190915260038152620c8c8d60ea1b60208201526129d6565b6001600160e01b0316600160e01b63ffffffff87160217875550610cf6915050565b8015610cf657835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b601b546001600160a01b031615611e6857611e68612a04565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b03909216908190559080158015611ec457506a0c097ce7bc90715b34b9f160241b8210155b15611eda57506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611ef085856128d3565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f91611f4991611f43918a16906395dd919390602401602060405180830381865afa158015611d5a573d5f803e3d5ffd5b83612b76565b6001600160a01b0387165f90815260146020526040902054909150611f6e90826125f1565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e906120199030908f908f908f908f908f90600401613582565b606060405180830381865afa158015612034573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061205891906135dd565b925092509250826014811115612070576120706134e5565b9b919a5098509650505050505050565b5f8061208c8585612b9d565b90506112ad61209a82612bc3565b846125f1565b6001600160a01b0381165f908152601060209081526040808320602b90925282205490916120cc61289a565b83549091505f906120ed9063ffffffff80851691600160e01b9004166128d3565b905080158015906120fd57508215155b156121e3575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216391906134ce565b90505f6121708386612929565b90505f825f0361218e5760405180602001604052805f815250612198565b612198828461296a565b604080516020810190915288546001600160e01b031681529091506121c190611de290836129ad565b6001600160e01b0316600160e01b63ffffffff87160217875550610af1915050565b8015610af157835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b601b546001600160a01b03161561222657612226612a04565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b0390921690819055908015801561228257506a0c097ce7bc90715b34b9f160241b8210155b1561229857506a0c097ce7bc90715b34b9f160241b5b5f60405180602001604052806122ae85856128d3565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f9161232291908816906370a0823190602401602060405180830381865afa1580156122fe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4391906134ce565b6001600160a01b0386165f9081526014602052604090205490915061234790826125f1565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f806123b78484612b9d565b9050610ba781612bc3565b5f6123cf610b1885611c4e565b6123d884611c4e565b6001600160a01b0384165f908152600291909101602052604090205460ff1661240257505f610f2a565b5f806124118587865f80612626565b9193509091505f905082601481111561242c5761242c6134e5565b14612443578160148111156117aa576117aa6134e5565b80156124505760046117aa565b5f9695505050505050565b6001600160a01b0382165f908152603560205260408120546001600160601b0316906124878284610cfe565b5f81815260096020526040902060060154909150600160601b900460ff166124c2576040516305b80c7960e41b815260040160405180910390fd5b6001600160601b038216158015906124f557506001600160601b0382165f9081526036602052604090206002015460ff16155b15610c2057604051632da4cc0560e01b81526001600160601b0383166004820152602401610dd5565b5f61252a836007611c00565b5f61253484611c4e565b905061253f81611c70565b6001600160a01b0383165f90815260028201602052604090205460ff161561256a575f915050610d19565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b5f610f2a8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612bda565b5f80808084600181111561263c5761263c6134e5565b0361264a5761264a88612c13565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e906120199030908f908f908f908f908f90600401613582565b5f546001600160a01b03163314611bfe5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610dd5565b6001600160a01b038116611cb55760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610dd5565b61272c610b1884611c4e565b6001600160a01b0383165f908152602b602052604090205482146127a857612753836120a0565b6001600160a01b0383165f818152602b602052604090819020849055517fa9ff26899e4982e7634afa9f70115dcfb61a17d6e8cdd91aa837671d0ff40ba69061279f9085815260200190565b60405180910390a25b6001600160a01b0383165f908152602a6020526040902054811461104d575f6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561280e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061283291906134ce565b905290506128408482611cb8565b6001600160a01b0384165f818152602a602052604090819020849055517f0c62c1bc89ec4c40dccb4d21543e782c5ba43897c0075d108d8964181ea3c51b9061288c9085815260200190565b60405180910390a250505050565b5f6128ce4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612d2a565b905090565b5f610f2a8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612d51565b5f610f2a61292284670de0b6b3a7640000612929565b8351612d7f565b5f610f2a83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612db1565b60408051602081019091525f815260405180602001604052806129a461299e866a0c097ce7bc90715b34b9f160241b612929565b85612d7f565b90529392505050565b60408051602081019091525f815260405180602001604052806129a4855f0151855f01516125f1565b5f81600160e01b84106129fc5760405162461bcd60e51b8152600401610dd59190613608565b509192915050565b601c541580612a145750601c5443105b15612a1b57565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015612a65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a8991906134ce565b9050805f03612a96575050565b5f80612aa443601c546128d3565b90505f612ab3601a5483612929565b9050808410612ac457809250612ac8565b8392505b601d54831015612ad9575050505050565b43601c55601b54612af7906001600160a01b03878116911685612e01565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ada575f80fd5b5f6a0c097ce7bc90715b34b9f160241b612b9384845f0151612929565b610f2a919061362e565b60408051602081019091525f815260405180602001604052806129a4855f015185612929565b80515f90610d1990670de0b6b3a76400009061362e565b5f80612be6848661364d565b90508285821015612c0a5760405162461bcd60e51b8152600401610dd59190613608565b50949350505050565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015612c8957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612c6b575b505083519394505f925050505b81811015610af157836001600160a01b031663a9c3cab1848381518110612cbf57612cbf61356e565b60200260200101516040518263ffffffff1660e01b8152600401612cf291906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015612d09575f80fd5b505af1158015612d1b573d5f803e3d5ffd5b50505050806001019050612c96565b5f8164010000000084106129fc5760405162461bcd60e51b8152600401610dd59190613608565b5f8184841115612d745760405162461bcd60e51b8152600401610dd59190613608565b50610ba78385613660565b5f610f2a83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612e53565b5f831580612dbd575082155b15612dc957505f610f2a565b5f612dd48486613673565b905083612de1868361362e565b148390612c0a5760405162461bcd60e51b8152600401610dd59190613608565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261104d908490612e7e565b5f8183612e735760405162461bcd60e51b8152600401610dd59190613608565b50610ba7838561362e565b5f612ed2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f519092919063ffffffff16565b905080515f1480612ef2575080806020019051810190612ef2919061368a565b61104d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610dd5565b6060610ba784845f85855f80866001600160a01b03168587604051612f7691906136a9565b5f6040518083038185875af1925050503d805f8114612fb0576040519150601f19603f3d011682016040523d82523d5f602084013e612fb5565b606091505b5091509150612fc687838387612fd1565b979650505050505050565b6060831561303f5782515f03613038576001600160a01b0385163b6130385760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dd5565b5081610ba7565b610ba783838151156130545781518083602001fd5b8060405162461bcd60e51b8152600401610dd59190613608565b6001600160a01b0381168114611cb5575f80fd5b5f60208284031215613092575f80fd5b8135610f2a8161306e565b5f80604083850312156130ae575f80fd5b82356130b98161306e565b915060208301356130c98161306e565b809150509250929050565b5f805f805f60a086880312156130e8575f80fd5b85356130f38161306e565b945060208601356131038161306e565b935060408601356131138161306e565b94979396509394606081013594506080013592915050565b5f805f806080858703121561313e575f80fd5b84356131498161306e565b935060208501356131598161306e565b925060408501356131698161306e565b9396929550929360600135925050565b5f805f806080858703121561318c575f80fd5b84356131978161306e565b935060208501356131a78161306e565b93969395505050506040820135916060013590565b5f805f805f8060c087890312156131d1575f80fd5b86356131dc8161306e565b955060208701356131ec8161306e565b945060408701356131fc8161306e565b9350606087013561320c8161306e565b9598949750929560808101359460a0909101359350915050565b80356001600160601b038116811461323c575f80fd5b919050565b5f8060408385031215613252575f80fd5b6130b983613226565b5f805f6060848603121561326d575f80fd5b83356132788161306e565b925060208401356132888161306e565b929592945050506040919091013590565b5f602082840312156132a9575f80fd5b5035919050565b5f805f805f60a086880312156132c4575f80fd5b85356132cf8161306e565b945060208601356132df8161306e565b935060408601356132ef8161306e565b925060608601356132ff8161306e565b949793965091946080013592915050565b5f60208284031215613320575f80fd5b610f2a82613226565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6133696060830186613329565b931515602083015250901515604090910152919050565b5f8060408385031215613391575f80fd5b823561339c8161306e565b946020939093013593505050565b5f80604083850312156133bb575f80fd5b82356133c68161306e565b91506020830135600981106130c9575f80fd5b5f8083601f8401126133e9575f80fd5b50813567ffffffffffffffff811115613400575f80fd5b6020830191508360208260051b850101111561341a575f80fd5b9250929050565b5f805f805f8060608789031215613436575f80fd5b863567ffffffffffffffff8082111561344d575f80fd5b6134598a838b016133d9565b90985096506020890135915080821115613471575f80fd5b61347d8a838b016133d9565b90965094506040890135915080821115613495575f80fd5b506134a289828a016133d9565b979a9699509497509295939492505050565b6001600160a01b0392831681529116602082015260400190565b5f602082840312156134de575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c9082168061350d57607f821691505b60208210810361352b57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613541575f80fd5b8151610f2a8161306e565b5f806040838503121561355d575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101600283106135cc57634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f606084860312156135ef575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610f2a6020830184613329565b634e487b7160e01b5f52601160045260245ffd5b5f8261364857634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610d1957610d1961361a565b81810381811115610d1957610d1961361a565b8082028115828204841417610d1957610d1961361a565b5f6020828403121561369a575f80fd5b81518015158114610f2a575f80fd5b5f82518060208501845e5f92019182525091905056fea264697066735822122055915414693085a25cc251c838723a918f3c10d5cbe09d59bfeae8b43296cc1e64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106103eb575f3560e01c80637fb8e8cd1161020b578063c7ee005e1161011f578063e0f6123d116100b4578063eabe7d9111610084578063eabe7d9114610a12578063ead1a8a014610a25578063f445d70314610a38578063f851a44014610a65578063fa6331d814610a77575f80fd5b8063e0f6123d1461099d578063e37d4b79146109bf578063e85a2960146109f6578063e875544614610a09575f80fd5b8063d7c46d2d116100ef578063d7c46d2d1461094c578063da3d454c14610964578063dce1544914610977578063dcfbc0c71461098a575f80fd5b8063c7ee005e1461090c578063d02f73511461091f578063d3270f9914610932578063d463654c14610945575f80fd5b8063b2eafc39116101a0578063bdcdc25811610170578063bdcdc2581461089f578063bec04f72146108b2578063bf32442d146108bb578063c5b4db55146108cc578063c5f956af146108f9575f80fd5b8063b2eafc39146107ff578063b8324c7c14610812578063bb82aa5e1461086d578063bbb8864a14610880575f80fd5b806394b2294b116101db57806394b2294b146107ae57806396c99064146107b75780639bb27d62146107d9578063a657e579146107ec575f80fd5b80637fb8e8cd1461074d5780638a7dc1651461075a5780638c1ac18a146107795780639254f5e51461079b575f80fd5b80634d99c776116103025780635ec88c7911610297578063719f701b11610267578063719f701b146106cc57806373769099146106d557806376551383146107155780637d172bd5146107275780637dc0d1d01461073a575f80fd5b80635ec88c79146106805780635fc7e71e146106935780636a56947e146106a65780636d35bf91146106b9575f80fd5b8063528a174c116102d2578063528a174c1461062857806352d84d1e1461063b5780635c7786051461064e5780635dd3fc9d14610661575f80fd5b80634d99c776146105c15780634e79238f146105d45780634ef4c3e11461060257806351dff98914610615575f80fd5b806324a3d6221161038357806341a18d2c1161035357806341a18d2c1461053f57806341c728b914610569578063425fad581461057c57806347ef3b3b1461058f5780634a584432146105a2575f80fd5b806324a3d622146104ed57806326782247146105005780632bc7e29e146105135780634088c73e14610532575f80fd5b806310b98338116103be57806310b983381461045d5780631ededc911461049a57806321af4569146104af57806324008a62146104da575f80fd5b806302c3bcbb146103ef57806304ef9d581461042157806308e0225c1461042a5780630db4b4e514610454575b5f80fd5b61040e6103fd366004613082565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61040e60225481565b61040e61043836600461309d565b601360209081525f928352604080842090915290825290205481565b61040e601d5481565b61048a61046b36600461309d565b602c60209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610418565b6104ad6104a83660046130d4565b610a80565b005b601e546104c2906001600160a01b031681565b6040516001600160a01b039091168152602001610418565b61040e6104e836600461312b565b610af8565b600a546104c2906001600160a01b031681565b6001546104c2906001600160a01b031681565b61040e610521366004613082565b60166020525f908152604090205481565b60185461048a9060ff1681565b61040e61054d36600461309d565b601260209081525f928352604080842090915290825290205481565b6104ad610577366004613179565b610baf565b60185461048a9062010000900460ff1681565b6104ad61059d3660046131bc565b610c26565b61040e6105b0366004613082565b601f6020525f908152604090205481565b61040e6105cf366004613241565b610cfe565b6105e76105e2366004613179565b610d1f565b60408051938452602084019290925290820152606001610418565b61040e61061036600461325b565b610d59565b6104ad610623366004613179565b610f31565b6105e7610636366004613082565b610f7d565b6104c2610649366004613299565b610fb4565b6104ad61065c36600461325b565b610fdc565b61040e61066f366004613082565b602b6020525f908152604090205481565b6105e761068e366004613082565b611052565b61040e6106a13660046132b0565b611066565b6104ad6106b436600461312b565b6112b6565b6104ad6106c73660046132b0565b611358565b61040e601c5481565b6106fd6106e3366004613082565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610418565b60185461048a90610100900460ff1681565b601b546104c2906001600160a01b031681565b6004546104c2906001600160a01b031681565b60395461048a9060ff1681565b61040e610768366004613082565b60146020525f908152604090205481565b61048a610787366004613082565b602d6020525f908152604090205460ff1681565b6015546104c2906001600160a01b031681565b61040e60075481565b6107ca6107c5366004613310565b6113fa565b60405161041893929190613357565b6025546104c2906001600160a01b031681565b6037546106fd906001600160601b031681565b6020546104c2906001600160a01b031681565b610849610820366004613082565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610418565b6002546104c2906001600160a01b031681565b61040e61088e366004613082565b602a6020525f908152604090205481565b61040e6108ad36600461312b565b6114a7565b61040e60175481565b6033546001600160a01b03166104c2565b6108e16a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b039091168152602001610418565b6021546104c2906001600160a01b031681565b6031546104c2906001600160a01b031681565b61040e61092d3660046132b0565b6114f3565b6026546104c2906001600160a01b031681565b6106fd5f81565b6039546104c29061010090046001600160a01b031681565b61040e61097236600461325b565b61166c565b6104c2610985366004613380565b6119f7565b6003546104c2906001600160a01b031681565b61048a6109ab366004613082565b60386020525f908152604090205460ff1681565b6108496109cd366004613082565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61048a610a043660046133aa565b611a2b565b61040e60055481565b61040e610a2036600461325b565b611a6f565b6104ad610a33366004613421565b611abb565b61048a610a4636600461309d565b603260209081525f928352604080842090915290825290205460ff1681565b5f546104c2906001600160a01b031681565b61040e601a5481565b6031546001600160a01b031615610af1576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610ac390869089906004016134b4565b5f604051808303815f87803b158015610ada575f80fd5b505af1158015610aec573d5f803e3d5ffd5b505050505b5050505050565b5f610b01611bb0565b610b0c856003611c00565b610b1d610b1886611c4e565b611c70565b5f6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b8991906134ce565b90529050610b978682611cb8565b610ba2868583611e4f565b5f9150505b949350505050565b6031546001600160a01b031615610c20576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610bf290869088906004016134b4565b5f604051808303815f87803b158015610c09575f80fd5b505af1158015610c1b573d5f803e3d5ffd5b505050505b50505050565b6031546001600160a01b031615610cf6576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610c699086908a906004016134b4565b5f604051808303815f87803b158015610c80575f80fd5b505af1158015610c92573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610cc89087908a906004016134b4565b5f604051808303815f87803b158015610cdf575f80fd5b505af1158015610cf1573d5f803e3d5ffd5b505050505b505050505050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b5f805f805f80610d328a8a8a8a5f611fd3565b925092509250826014811115610d4a57610d4a6134e5565b9a919950975095505050505050565b5f610d62611bb0565b610d6c845f611c00565b610d78610b1885611c4e565b6001600160a01b0384165f9081526027602052604081205490819003610dde5760405162461bcd60e51b815260206004820152601660248201527506d61726b657420737570706c792063617020697320360541b60448201526064015b60405180910390fd5b5f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3f91906134ce565b90505f6040518060200160405280886001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ead91906134ce565b905290505f610ebd828488612080565b905083811115610f0f5760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420737570706c79206361702072656163686564000000000000006044820152606401610dd5565b610f18886120a0565b610f22888861220d565b5f9450505050505b9392505050565b80151580610f3d575081155b610baf5760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610dd5565b5f805f805f80610f90875f805f80611fd3565b925092509250826014811115610fa857610fa86134e5565b97919650945092505050565b600d8181548110610fc3575f80fd5b5f918252602090912001546001600160a01b0316905081565b6031546001600160a01b03161561104d576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d169061101f90859087906004016134b4565b5f604051808303815f87803b158015611036575f80fd5b505af1158015611048573d5f803e3d5ffd5b505050505b505050565b5f805f805f80610f90875f805f6001611fd3565b5f61106f611bb0565b61107a866005611c00565b6025546001600160a01b0316158015906110a257506025546001600160a01b03858116911614155b156110af575060016112ad565b6110bb610b1886611c4e565b6015545f906001600160a01b0388811691161461114d576110de610b1888611c4e565b6040516395dd919360e01b81526001600160a01b0385811660048301528816906395dd919390602401602060405180830381865afa158015611122573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061114691906134ce565b90506111bc565b601554604051633c617c9160e11b81526001600160a01b038681166004830152909116906378c2f92290602401602060405180830381865afa158015611195573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111b991906134ce565b90505b6001600160a01b0387165f908152602d602052604090205460ff168061120657506001600160a01b038085165f908152603260209081526040808320938b168352929052205460ff165b15611224578083111561121e5760115b9150506112ad565b5f611216565b5f80611234865f805f6001611fd3565b9193509091505f905082601481111561124f5761124f6134e5565b1461127057816014811115611266576112666134e5565b93505050506112ad565b805f0361127e576003611266565b6112986040518060200160405280600554815250846123ab565b8511156112a6576011611266565b5f93505050505b95945050505050565b6031546001600160a01b031615610c20576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906112f990869088906004016134b4565b5f604051808303815f87803b158015611310575f80fd5b505af1158015611322573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610bf290859088906004016134b4565b6031546001600160a01b031615610af1576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d169061139b90859089906004016134b4565b5f604051808303815f87803b1580156113b2575f80fd5b505af11580156113c4573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610ac390869089906004016134b4565b60366020525f9081526040902080548190611414906134f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611440906134f9565b801561148b5780601f106114625761010080835404028352916020019161148b565b820191905f5260205f20905b81548152906001019060200180831161146e57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6114b0611bb0565b6114bb856006611c00565b5f6114c78686856123c2565b905080156114d6579050610ba7565b6114df866120a0565b6114e9868661220d565b610ba2868561220d565b5f6114fc611bb0565b611507866004611c00565b5f61151187611c4e565b905061151c81611c70565b6001600160a01b0384165f90815260028201602052604090205460ff16611544576013611216565b6015546001600160a01b0387811691161461156557611565610b1887611c4e565b856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115c59190613531565b6001600160a01b0316876001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561160a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061162e9190613531565b6001600160a01b031614611643576002611216565b61164c876120a0565b611656878561220d565b611660878661220d565b5f979650505050505050565b5f611675611bb0565b611680846002611c00565b61168c610b1885611c4e565b611696838561245b565b6001600160a01b0384165f908152601f6020526040812054908190036116f75760405162461bcd60e51b815260206004820152601660248201527506d61726b657420626f72726f772063617020697320360541b6044820152606401610dd5565b61170085611c4e565b6001600160a01b0385165f908152600291909101602052604090205460ff166117b557336001600160a01b038616146117735760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba103132903b2a37b5b2b760591b6044820152606401610dd5565b5f61177e868661251e565b90505f816014811115611793576117936134e5565b146117b3578060148111156117aa576117aa6134e5565b92505050610f2a565b505b6039546040516388142b6b60e01b81526001600160a01b0387811660048301525f928392610100909104909116906388142b6b906024016040805180830381865afa158015611806573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061182a919061354c565b91509150815f148061183a575080155b1561184b57600d9350505050610f2a565b5f6118b5886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561188b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118af91906134ce565b876125f1565b9050838111156119075760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610dd5565b5f80611916898b5f8b5f612626565b9193509091505f9050826014811115611931576119316134e5565b1461195557816014811115611948576119486134e5565b9650505050505050610f2a565b8015611962576004611948565b5f60405180602001604052808c6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ce91906134ce565b905290506119dc8b82611cb8565b6119e78b8b83611e4f565b5f9b9a5050505050505050505050565b6008602052815f5260405f208181548110611a10575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611a5557611a556134e5565b815260208101919091526040015f205460ff169392505050565b5f611a78611bb0565b611a83846001611c00565b5f611a8f8585856123c2565b90508015611a9e579050610f2a565b611aa7856120a0565b611ab1858561220d565b5f95945050505050565b611ac3612688565b848381148015611ad257508082145b611b0e5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610dd5565b5f5b81811015610c1b57611b47888883818110611b2d57611b2d61356e565b9050602002016020810190611b429190613082565b6126d2565b611ba8888883818110611b5c57611b5c61356e565b9050602002016020810190611b719190613082565b878784818110611b8357611b8361356e565b90506020020135868685818110611b9c57611b9c61356e565b90506020020135612720565b600101611b10565b60185462010000900460ff1615611bfe5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610dd5565b565b611c0a8282611a2b565b15611c4a5760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610dd5565b5050565b5f60095f611c5c5f85610cfe565b81526020019081526020015f209050919050565b805460ff16611cb55760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610dd5565b50565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611ce461289a565b83549091505f90611d059063ffffffff80851691600160e01b9004166128d3565b90508015801590611d1557508215155b15611e24575f611d84876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d7e91906134ce565b8761290c565b90505f611d918386612929565b90505f825f03611daf5760405180602001604052805f815250611db9565b611db9828461296a565b604080516020810190915288546001600160e01b03168152909150611e0290611de290836129ad565b516040805180820190915260038152620c8c8d60ea1b60208201526129d6565b6001600160e01b0316600160e01b63ffffffff87160217875550610cf6915050565b8015610cf657835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b601b546001600160a01b031615611e6857611e68612a04565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b03909216908190559080158015611ec457506a0c097ce7bc90715b34b9f160241b8210155b15611eda57506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611ef085856128d3565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f91611f4991611f43918a16906395dd919390602401602060405180830381865afa158015611d5a573d5f803e3d5ffd5b83612b76565b6001600160a01b0387165f90815260146020526040902054909150611f6e90826125f1565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e906120199030908f908f908f908f908f90600401613582565b606060405180830381865afa158015612034573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061205891906135dd565b925092509250826014811115612070576120706134e5565b9b919a5098509650505050505050565b5f8061208c8585612b9d565b90506112ad61209a82612bc3565b846125f1565b6001600160a01b0381165f908152601060209081526040808320602b90925282205490916120cc61289a565b83549091505f906120ed9063ffffffff80851691600160e01b9004166128d3565b905080158015906120fd57508215155b156121e3575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216391906134ce565b90505f6121708386612929565b90505f825f0361218e5760405180602001604052805f815250612198565b612198828461296a565b604080516020810190915288546001600160e01b031681529091506121c190611de290836129ad565b6001600160e01b0316600160e01b63ffffffff87160217875550610af1915050565b8015610af157835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b601b546001600160a01b03161561222657612226612a04565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b0390921690819055908015801561228257506a0c097ce7bc90715b34b9f160241b8210155b1561229857506a0c097ce7bc90715b34b9f160241b5b5f60405180602001604052806122ae85856128d3565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f9161232291908816906370a0823190602401602060405180830381865afa1580156122fe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4391906134ce565b6001600160a01b0386165f9081526014602052604090205490915061234790826125f1565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f806123b78484612b9d565b9050610ba781612bc3565b5f6123cf610b1885611c4e565b6123d884611c4e565b6001600160a01b0384165f908152600291909101602052604090205460ff1661240257505f610f2a565b5f806124118587865f80612626565b9193509091505f905082601481111561242c5761242c6134e5565b14612443578160148111156117aa576117aa6134e5565b80156124505760046117aa565b5f9695505050505050565b6001600160a01b0382165f908152603560205260408120546001600160601b0316906124878284610cfe565b5f81815260096020526040902060060154909150600160601b900460ff166124c2576040516305b80c7960e41b815260040160405180910390fd5b6001600160601b038216158015906124f557506001600160601b0382165f9081526036602052604090206002015460ff16155b15610c2057604051632da4cc0560e01b81526001600160601b0383166004820152602401610dd5565b5f61252a836007611c00565b5f61253484611c4e565b905061253f81611c70565b6001600160a01b0383165f90815260028201602052604090205460ff161561256a575f915050610d19565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b5f610f2a8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612bda565b5f80808084600181111561263c5761263c6134e5565b0361264a5761264a88612c13565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e906120199030908f908f908f908f908f90600401613582565b5f546001600160a01b03163314611bfe5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610dd5565b6001600160a01b038116611cb55760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610dd5565b61272c610b1884611c4e565b6001600160a01b0383165f908152602b602052604090205482146127a857612753836120a0565b6001600160a01b0383165f818152602b602052604090819020849055517fa9ff26899e4982e7634afa9f70115dcfb61a17d6e8cdd91aa837671d0ff40ba69061279f9085815260200190565b60405180910390a25b6001600160a01b0383165f908152602a6020526040902054811461104d575f6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561280e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061283291906134ce565b905290506128408482611cb8565b6001600160a01b0384165f818152602a602052604090819020849055517f0c62c1bc89ec4c40dccb4d21543e782c5ba43897c0075d108d8964181ea3c51b9061288c9085815260200190565b60405180910390a250505050565b5f6128ce4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612d2a565b905090565b5f610f2a8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612d51565b5f610f2a61292284670de0b6b3a7640000612929565b8351612d7f565b5f610f2a83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612db1565b60408051602081019091525f815260405180602001604052806129a461299e866a0c097ce7bc90715b34b9f160241b612929565b85612d7f565b90529392505050565b60408051602081019091525f815260405180602001604052806129a4855f0151855f01516125f1565b5f81600160e01b84106129fc5760405162461bcd60e51b8152600401610dd59190613608565b509192915050565b601c541580612a145750601c5443105b15612a1b57565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015612a65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a8991906134ce565b9050805f03612a96575050565b5f80612aa443601c546128d3565b90505f612ab3601a5483612929565b9050808410612ac457809250612ac8565b8392505b601d54831015612ad9575050505050565b43601c55601b54612af7906001600160a01b03878116911685612e01565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ada575f80fd5b5f6a0c097ce7bc90715b34b9f160241b612b9384845f0151612929565b610f2a919061362e565b60408051602081019091525f815260405180602001604052806129a4855f015185612929565b80515f90610d1990670de0b6b3a76400009061362e565b5f80612be6848661364d565b90508285821015612c0a5760405162461bcd60e51b8152600401610dd59190613608565b50949350505050565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015612c8957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612c6b575b505083519394505f925050505b81811015610af157836001600160a01b031663a9c3cab1848381518110612cbf57612cbf61356e565b60200260200101516040518263ffffffff1660e01b8152600401612cf291906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015612d09575f80fd5b505af1158015612d1b573d5f803e3d5ffd5b50505050806001019050612c96565b5f8164010000000084106129fc5760405162461bcd60e51b8152600401610dd59190613608565b5f8184841115612d745760405162461bcd60e51b8152600401610dd59190613608565b50610ba78385613660565b5f610f2a83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612e53565b5f831580612dbd575082155b15612dc957505f610f2a565b5f612dd48486613673565b905083612de1868361362e565b148390612c0a5760405162461bcd60e51b8152600401610dd59190613608565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261104d908490612e7e565b5f8183612e735760405162461bcd60e51b8152600401610dd59190613608565b50610ba7838561362e565b5f612ed2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f519092919063ffffffff16565b905080515f1480612ef2575080806020019051810190612ef2919061368a565b61104d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610dd5565b6060610ba784845f85855f80866001600160a01b03168587604051612f7691906136a9565b5f6040518083038185875af1925050503d805f8114612fb0576040519150601f19603f3d011682016040523d82523d5f602084013e612fb5565b606091505b5091509150612fc687838387612fd1565b979650505050505050565b6060831561303f5782515f03613038576001600160a01b0385163b6130385760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dd5565b5081610ba7565b610ba783838151156130545781518083602001fd5b8060405162461bcd60e51b8152600401610dd59190613608565b6001600160a01b0381168114611cb5575f80fd5b5f60208284031215613092575f80fd5b8135610f2a8161306e565b5f80604083850312156130ae575f80fd5b82356130b98161306e565b915060208301356130c98161306e565b809150509250929050565b5f805f805f60a086880312156130e8575f80fd5b85356130f38161306e565b945060208601356131038161306e565b935060408601356131138161306e565b94979396509394606081013594506080013592915050565b5f805f806080858703121561313e575f80fd5b84356131498161306e565b935060208501356131598161306e565b925060408501356131698161306e565b9396929550929360600135925050565b5f805f806080858703121561318c575f80fd5b84356131978161306e565b935060208501356131a78161306e565b93969395505050506040820135916060013590565b5f805f805f8060c087890312156131d1575f80fd5b86356131dc8161306e565b955060208701356131ec8161306e565b945060408701356131fc8161306e565b9350606087013561320c8161306e565b9598949750929560808101359460a0909101359350915050565b80356001600160601b038116811461323c575f80fd5b919050565b5f8060408385031215613252575f80fd5b6130b983613226565b5f805f6060848603121561326d575f80fd5b83356132788161306e565b925060208401356132888161306e565b929592945050506040919091013590565b5f602082840312156132a9575f80fd5b5035919050565b5f805f805f60a086880312156132c4575f80fd5b85356132cf8161306e565b945060208601356132df8161306e565b935060408601356132ef8161306e565b925060608601356132ff8161306e565b949793965091946080013592915050565b5f60208284031215613320575f80fd5b610f2a82613226565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6133696060830186613329565b931515602083015250901515604090910152919050565b5f8060408385031215613391575f80fd5b823561339c8161306e565b946020939093013593505050565b5f80604083850312156133bb575f80fd5b82356133c68161306e565b91506020830135600981106130c9575f80fd5b5f8083601f8401126133e9575f80fd5b50813567ffffffffffffffff811115613400575f80fd5b6020830191508360208260051b850101111561341a575f80fd5b9250929050565b5f805f805f8060608789031215613436575f80fd5b863567ffffffffffffffff8082111561344d575f80fd5b6134598a838b016133d9565b90985096506020890135915080821115613471575f80fd5b61347d8a838b016133d9565b90965094506040890135915080821115613495575f80fd5b506134a289828a016133d9565b979a9699509497509295939492505050565b6001600160a01b0392831681529116602082015260400190565b5f602082840312156134de575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c9082168061350d57607f821691505b60208210810361352b57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613541575f80fd5b8151610f2a8161306e565b5f806040838503121561355d575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101600283106135cc57634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f606084860312156135ef575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610f2a6020830184613329565b634e487b7160e01b5f52601160045260245ffd5b5f8261364857634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610d1957610d1961361a565b81810381811115610d1957610d1961361a565b8082028115828204841417610d1957610d1961361a565b5f6020828403121561369a575f80fd5b81518015158114610f2a575f80fd5b5f82518060208501845e5f92019182525091905056fea264697066735822122055915414693085a25cc251c838723a918f3c10d5cbe09d59bfeae8b43296cc1e64736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This facet contains all the hooks used while transferring the assets", @@ -2129,6 +2142,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "flashLoanPaused()": { "notice": "Whether flash loans are paused system-wide" }, @@ -2277,7 +2293,7 @@ "storageLayout": { "storage": [ { - "astId": 1677, + "astId": 9226, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "admin", "offset": 0, @@ -2285,7 +2301,7 @@ "type": "t_address" }, { - "astId": 1680, + "astId": 9229, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "pendingAdmin", "offset": 0, @@ -2293,7 +2309,7 @@ "type": "t_address" }, { - "astId": 1683, + "astId": 9232, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "comptrollerImplementation", "offset": 0, @@ -2301,7 +2317,7 @@ "type": "t_address" }, { - "astId": 1686, + "astId": 9235, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -2309,15 +2325,15 @@ "type": "t_address" }, { - "astId": 1693, + "astId": 9242, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)992" + "type": "t_contract(ResilientOracleInterface)7913" }, { - "astId": 1696, + "astId": 9245, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "closeFactorMantissa", "offset": 0, @@ -2325,7 +2341,7 @@ "type": "t_uint256" }, { - "astId": 1699, + "astId": 9248, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -2333,7 +2349,7 @@ "type": "t_uint256" }, { - "astId": 1702, + "astId": 9251, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "maxAssets", "offset": 0, @@ -2341,23 +2357,23 @@ "type": "t_uint256" }, { - "astId": 1709, + "astId": 9258, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)" }, { - "astId": 1743, + "astId": 9292, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)" }, { - "astId": 1746, + "astId": 9295, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "pauseGuardian", "offset": 0, @@ -2365,7 +2381,7 @@ "type": "t_address" }, { - "astId": 1749, + "astId": 9298, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -2373,7 +2389,7 @@ "type": "t_bool" }, { - "astId": 1752, + "astId": 9301, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -2381,7 +2397,7 @@ "type": "t_bool" }, { - "astId": 1755, + "astId": 9304, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "transferGuardianPaused", "offset": 22, @@ -2389,7 +2405,7 @@ "type": "t_bool" }, { - "astId": 1758, + "astId": 9307, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -2397,7 +2413,7 @@ "type": "t_bool" }, { - "astId": 1763, + "astId": 9312, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "mintGuardianPaused", "offset": 0, @@ -2405,7 +2421,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1768, + "astId": 9317, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -2413,15 +2429,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1780, + "astId": 9329, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)32634)dyn_storage" + "type": "t_array(t_contract(VToken)49461)dyn_storage" }, { - "astId": 1783, + "astId": 9332, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusRate", "offset": 0, @@ -2429,7 +2445,7 @@ "type": "t_uint256" }, { - "astId": 1788, + "astId": 9337, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusSpeeds", "offset": 0, @@ -2437,23 +2453,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1794, + "astId": 9343, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1800, + "astId": 9349, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1807, + "astId": 9356, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusSupplierIndex", "offset": 0, @@ -2461,7 +2477,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1814, + "astId": 9363, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -2469,7 +2485,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1819, + "astId": 9368, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusAccrued", "offset": 0, @@ -2477,15 +2493,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1823, + "astId": 9372, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)25733" + "type": "t_contract(VAIControllerInterface)42511" }, { - "astId": 1828, + "astId": 9377, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "mintedVAIs", "offset": 0, @@ -2493,7 +2509,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1831, + "astId": 9380, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "vaiMintRate", "offset": 0, @@ -2501,7 +2517,7 @@ "type": "t_uint256" }, { - "astId": 1834, + "astId": 9383, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -2509,7 +2525,7 @@ "type": "t_bool" }, { - "astId": 1836, + "astId": 9385, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -2517,7 +2533,7 @@ "type": "t_bool" }, { - "astId": 1839, + "astId": 9388, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "protocolPaused", "offset": 2, @@ -2525,7 +2541,7 @@ "type": "t_bool" }, { - "astId": 1842, + "astId": 9391, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusVAIRate", "offset": 0, @@ -2533,7 +2549,7 @@ "type": "t_uint256" }, { - "astId": 1848, + "astId": 9397, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -2541,7 +2557,7 @@ "type": "t_uint256" }, { - "astId": 1850, + "astId": 9399, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "vaiVaultAddress", "offset": 0, @@ -2549,7 +2565,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9401, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "releaseStartBlock", "offset": 0, @@ -2557,7 +2573,7 @@ "type": "t_uint256" }, { - "astId": 1854, + "astId": 9403, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "minReleaseAmount", "offset": 0, @@ -2565,7 +2581,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9409, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "borrowCapGuardian", "offset": 0, @@ -2573,7 +2589,7 @@ "type": "t_address" }, { - "astId": 1865, + "astId": 9414, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "borrowCaps", "offset": 0, @@ -2581,7 +2597,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1871, + "astId": 9420, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "treasuryGuardian", "offset": 0, @@ -2589,7 +2605,7 @@ "type": "t_address" }, { - "astId": 1874, + "astId": 9423, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "treasuryAddress", "offset": 0, @@ -2597,7 +2613,7 @@ "type": "t_address" }, { - "astId": 1877, + "astId": 9426, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "treasuryPercent", "offset": 0, @@ -2605,7 +2621,7 @@ "type": "t_uint256" }, { - "astId": 1885, + "astId": 9434, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -2613,7 +2629,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9439, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "lastContributorBlock", "offset": 0, @@ -2621,7 +2637,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1895, + "astId": 9444, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "liquidatorContract", "offset": 0, @@ -2629,15 +2645,15 @@ "type": "t_address" }, { - "astId": 1901, + "astId": 9450, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1660" + "type": "t_contract(ComptrollerLensInterface)9207" }, { - "astId": 1909, + "astId": 9458, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "supplyCaps", "offset": 0, @@ -2645,7 +2661,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1915, + "astId": 9464, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "accessControl", "offset": 0, @@ -2653,7 +2669,7 @@ "type": "t_address" }, { - "astId": 1922, + "astId": 9471, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_actionPaused", "offset": 0, @@ -2661,7 +2677,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1930, + "astId": 9479, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -2669,7 +2685,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1935, + "astId": 9484, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -2677,7 +2693,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1945, + "astId": 9494, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "approvedDelegates", "offset": 0, @@ -2685,7 +2701,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1953, + "astId": 9502, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -2693,23 +2709,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1972, + "astId": 9521, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)" }, { - "astId": 1977, + "astId": 9526, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)" }, { - "astId": 1980, + "astId": 9529, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_facetAddresses", "offset": 0, @@ -2717,15 +2733,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1987, + "astId": 9536, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)22911" + "type": "t_contract(IPrime)33730" }, { - "astId": 1997, + "astId": 9546, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -2733,7 +2749,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 2003, + "astId": 9552, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "xvs", "offset": 0, @@ -2741,7 +2757,7 @@ "type": "t_address" }, { - "astId": 2006, + "astId": 9555, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "xvsVToken", "offset": 0, @@ -2749,7 +2765,7 @@ "type": "t_address" }, { - "astId": 2028, + "astId": 9577, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "userPoolId", "offset": 0, @@ -2757,15 +2773,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2034, + "astId": 9583, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)2023_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)9572_storage)" }, { - "astId": 2037, + "astId": 9586, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "lastPoolId", "offset": 0, @@ -2773,7 +2789,7 @@ "type": "t_uint96" }, { - "astId": 2045, + "astId": 9594, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -2781,12 +2797,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2048, + "astId": 9597, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 9604, + "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)7883" } ], "types": { @@ -2807,8 +2831,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)32634)dyn_storage": { - "base": "t_contract(VToken)32634", + "t_array(t_contract(VToken)49461)dyn_storage": { + "base": "t_contract(VToken)49461", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -2823,37 +2847,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1660": { + "t_contract(ComptrollerLensInterface)9207": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)22911": { + "t_contract(IDeviationBoundedOracle)7883": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)33730": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)992": { + "t_contract(ResilientOracleInterface)7913": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)25733": { + "t_contract(VAIControllerInterface)42511": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)32634": { + "t_contract(VToken)49461": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)32634)dyn_storage" + "value": "t_array(t_contract(VToken)49461)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -2883,19 +2912,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1967_storage" + "value": "t_struct(FacetFunctionSelectors)9516_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1775_storage" + "value": "t_struct(VenusMarketState)9324_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2911,12 +2940,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1961_storage" + "value": "t_struct(FacetAddressAndPosition)9510_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -2925,31 +2954,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)2023_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)9572_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)2023_storage" + "value": "t_struct(PoolData)9572_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11427", + "key": "t_userDefinedValueType(PoolMarketId)19217", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1736_storage" + "value": "t_struct(Market)9285_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1961_storage": { + "t_struct(FacetAddressAndPosition)9510_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1958, + "astId": 9507, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "facetAddress", "offset": 0, @@ -2957,7 +2986,7 @@ "type": "t_address" }, { - "astId": 1960, + "astId": 9509, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "functionSelectorPosition", "offset": 20, @@ -2967,12 +2996,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1967_storage": { + "t_struct(FacetFunctionSelectors)9516_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1964, + "astId": 9513, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "functionSelectors", "offset": 0, @@ -2980,7 +3009,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1966, + "astId": 9515, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "facetAddressPosition", "offset": 0, @@ -2990,12 +3019,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1736_storage": { + "t_struct(Market)9285_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1712, + "astId": 9261, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isListed", "offset": 0, @@ -3003,7 +3032,7 @@ "type": "t_bool" }, { - "astId": 1715, + "astId": 9264, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -3011,7 +3040,7 @@ "type": "t_uint256" }, { - "astId": 1720, + "astId": 9269, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "accountMembership", "offset": 0, @@ -3019,7 +3048,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1723, + "astId": 9272, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isVenus", "offset": 0, @@ -3027,7 +3056,7 @@ "type": "t_bool" }, { - "astId": 1726, + "astId": 9275, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -3035,7 +3064,7 @@ "type": "t_uint256" }, { - "astId": 1729, + "astId": 9278, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -3043,7 +3072,7 @@ "type": "t_uint256" }, { - "astId": 1732, + "astId": 9281, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "poolId", "offset": 0, @@ -3051,7 +3080,7 @@ "type": "t_uint96" }, { - "astId": 1735, + "astId": 9284, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isBorrowAllowed", "offset": 12, @@ -3061,12 +3090,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)2023_storage": { + "t_struct(PoolData)9572_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 2012, + "astId": 9561, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "label", "offset": 0, @@ -3074,7 +3103,7 @@ "type": "t_string_storage" }, { - "astId": 2016, + "astId": 9565, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "vTokens", "offset": 0, @@ -3082,7 +3111,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 2019, + "astId": 9568, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isActive", "offset": 0, @@ -3090,7 +3119,7 @@ "type": "t_bool" }, { - "astId": 2022, + "astId": 9571, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -3100,12 +3129,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1775_storage": { + "t_struct(VenusMarketState)9324_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1771, + "astId": 9320, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "index", "offset": 0, @@ -3113,7 +3142,7 @@ "type": "t_uint224" }, { - "astId": 1774, + "astId": 9323, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "block", "offset": 28, @@ -3143,7 +3172,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11427": { + "t_userDefinedValueType(PoolMarketId)19217": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bscmainnet/RewardFacet.json b/deployments/bscmainnet/RewardFacet.json index e07390fca..bce4190af 100644 --- a/deployments/bscmainnet/RewardFacet.json +++ b/deployments/bscmainnet/RewardFacet.json @@ -1,5 +1,5 @@ { - "address": "0x7fcEc39e83f17469069b7A0f24A59B5BbEC0faBb", + "address": "0xFaC00Dc856F454BB674c8588d4CC16Edef9dc28b", "abi": [ { "inputs": [], @@ -703,6 +703,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -1346,28 +1359,28 @@ "type": "function" } ], - "transactionHash": "0xb9541773d9196d839808b2b8fd9a3494a3bf32097827f3f8b0c57d23f81a7e2d", + "transactionHash": "0xe0911eaf130b8c2bc7505da49f4a4ee7bbc36c116467c3932fc71a2c24c0acfe", "receipt": { "to": null, - "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x7fcEc39e83f17469069b7A0f24A59B5BbEC0faBb", - "transactionIndex": 152, - "gasUsed": "2419503", + "from": "0x9b0A3EAE7f174937d31745B710BbeA68e9D1BEf7", + "contractAddress": "0xFaC00Dc856F454BB674c8588d4CC16Edef9dc28b", + "transactionIndex": 36, + "gasUsed": "2493418", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xfece3b4ecb1739b9a1da126075a8f47de57aa74479d5c83bba501867e71a719e", - "transactionHash": "0xb9541773d9196d839808b2b8fd9a3494a3bf32097827f3f8b0c57d23f81a7e2d", + "blockHash": "0xc1b6026ed65c709c859d44debd692e1996569a27a8fe4c688de0aa313322baa9", + "transactionHash": "0xe0911eaf130b8c2bc7505da49f4a4ee7bbc36c116467c3932fc71a2c24c0acfe", "logs": [], - "blockNumber": 66295533, - "cumulativeGasUsed": "22967422", + "blockNumber": 95559352, + "cumulativeGasUsed": "7432982", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 4, - "solcInputHash": "7eb14bb68efebde544bca48fc6b525f5", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"VenusGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"VenusSeized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantXVS\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"collateral\",\"type\":\"bool\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimVenusAsCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSVTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"seizeVenus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the methods related to the reward functionality\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_grantXVS(address,uint256)\":{\"details\":\"Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall Note: If there is not enough XVS, we do not perform the transfer all\",\"params\":{\"amount\":\"The amount of XVS to (possibly) transfer\",\"recipient\":\"The address of the recipient to transfer XVS to\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"claimVenus(address)\":{\"params\":{\"holder\":\"The address to claim XVS for\"}},\"claimVenus(address,address[])\":{\"params\":{\"holder\":\"The address to claim XVS for\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenus(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim XVS earned by borrowing\",\"holders\":\"The addresses to claim XVS for\",\"suppliers\":\"Whether or not to claim XVS earned by supplying\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenus(address[],address[],bool,bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim XVS earned by borrowing\",\"collateral\":\"Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\",\"holders\":\"The addresses to claim XVS for\",\"suppliers\":\"Whether or not to claim XVS earned by supplying\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenusAsCollateral(address)\":{\"params\":{\"holder\":\"The address to claim XVS for\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"getXVSVTokenAddress()\":{\"returns\":{\"_0\":\"The address of XVS vToken\"}},\"seizeVenus(address[],address)\":{\"details\":\"Seize XVS tokens from the specified holders and transfer to recipient\",\"params\":{\"holders\":\"Addresses of the XVS holders\",\"recipient\":\"Address of the XVS token recipient\"},\"returns\":{\"_0\":\"The total amount of XVS tokens seized and transferred to recipient\"}}},\"title\":\"RewardFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedBorrowerVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a borrower\"},\"DistributedSupplierVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a supplier\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"VenusGranted(address,uint256)\":{\"notice\":\"Emitted when Venus is granted by admin\"},\"VenusSeized(address,uint256)\":{\"notice\":\"Emitted when XVS are seized for the holder\"}},\"kind\":\"user\",\"methods\":{\"_grantXVS(address,uint256)\":{\"notice\":\"Transfer XVS to the recipient\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"claimVenus(address)\":{\"notice\":\"Claim all the xvs accrued by holder in all markets and VAI\"},\"claimVenus(address,address[])\":{\"notice\":\"Claim all the xvs accrued by holder in the specified markets\"},\"claimVenus(address[],address[],bool,bool)\":{\"notice\":\"Claim all xvs accrued by the holders\"},\"claimVenus(address[],address[],bool,bool,bool)\":{\"notice\":\"Claim all xvs accrued by the holders\"},\"claimVenusAsCollateral(address)\":{\"notice\":\"Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"getXVSVTokenAddress()\":{\"notice\":\"Returns the XVS vToken address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"seizeVenus(address[],address)\":{\"notice\":\"Seize XVS rewards allocated to holders\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract provides the external functions related to all claims and rewards of the protocol\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/RewardFacet.sol\":\"RewardFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/RewardFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { IRewardFacet } from \\\"../interfaces/IRewardFacet.sol\\\";\\nimport { XVSRewardsHelper } from \\\"./XVSRewardsHelper.sol\\\";\\nimport { VBep20Interface } from \\\"../../../Tokens/VTokens/VTokenInterfaces.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title RewardFacet\\n * @author Venus\\n * @dev This facet contains all the methods related to the reward functionality\\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\\n */\\ncontract RewardFacet is IRewardFacet, XVSRewardsHelper {\\n /// @notice Emitted when Venus is granted by admin\\n event VenusGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when XVS are seized for the holder\\n event VenusSeized(address indexed holder, uint256 amount);\\n\\n using SafeERC20 for IERC20;\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in all markets and VAI\\n * @param holder The address to claim XVS for\\n */\\n function claimVenus(address holder) public {\\n return claimVenus(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in the specified markets\\n * @param holder The address to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n */\\n function claimVenus(address holder, VToken[] memory vTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimVenus(holders, vTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all xvs accrued by the holders\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n */\\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\\n claimVenus(holders, vTokens, borrowers, suppliers, false);\\n }\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\\n * @param holder The address to claim XVS for\\n */\\n function claimVenusAsCollateral(address holder) external {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimVenus(holders, allMarkets, true, true, true);\\n }\\n\\n /**\\n * @notice Transfer XVS to the user with user's shortfall considered\\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\\n * @param user The address of the user to transfer XVS to\\n * @param amount The amount of XVS to (possibly) transfer\\n * @param shortfall The shortfall of the user\\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\\n * @return The amount of XVS which was NOT transferred to the user\\n */\\n function grantXVSInternal(\\n address user,\\n uint256 amount,\\n uint256 shortfall,\\n bool collateral\\n ) internal returns (uint256) {\\n // If the user is blacklisted, they can't get XVS rewards\\n require(\\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\\n \\\"Blacklisted\\\"\\n );\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n if (amount == 0 || amount > xvs_.balanceOf(address(this))) {\\n return amount;\\n }\\n\\n if (shortfall == 0) {\\n xvs_.safeTransfer(user, amount);\\n return 0;\\n }\\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\\n // anything, otherwise, we will transfer the pending xvs as collateral to\\n // vXVS token and mint vXVS for the user\\n //\\n // If mintBehalf failed, don't grant any xvs\\n require(collateral, \\\"bankrupt\\\");\\n\\n address xvsVToken_ = xvsVToken;\\n\\n xvs_.safeApprove(xvsVToken_, 0);\\n xvs_.safeApprove(xvsVToken_, amount);\\n require(VBep20Interface(xvsVToken_).mintBehalf(user, amount) == uint256(Error.NO_ERROR), \\\"mint behalf error\\\");\\n\\n // set venusAccrued[user] to 0\\n return 0;\\n }\\n\\n /*** Venus Distribution Admin ***/\\n\\n /**\\n * @notice Transfer XVS to the recipient\\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\\n * Note: If there is not enough XVS, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer XVS to\\n * @param amount The amount of XVS to (possibly) transfer\\n */\\n function _grantXVS(address recipient, uint256 amount) external {\\n ensureAdmin();\\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\\n require(amountLeft == 0, \\\"no xvs\\\");\\n emit VenusGranted(recipient, amount);\\n }\\n\\n /**\\n * @dev Seize XVS tokens from the specified holders and transfer to recipient\\n * @notice Seize XVS rewards allocated to holders\\n * @param holders Addresses of the XVS holders\\n * @param recipient Address of the XVS token recipient\\n * @return The total amount of XVS tokens seized and transferred to recipient\\n */\\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256) {\\n ensureAllowed(\\\"seizeVenus(address[],address)\\\");\\n\\n uint256 holdersLength = holders.length;\\n uint256 totalHoldings;\\n\\n updateAndDistributeRewardsInternal(holders, allMarkets, true, true);\\n for (uint256 j; j < holdersLength; ++j) {\\n address holder = holders[j];\\n uint256 userHolding = venusAccrued[holder];\\n\\n if (userHolding != 0) {\\n totalHoldings += userHolding;\\n delete venusAccrued[holder];\\n }\\n\\n emit VenusSeized(holder, userHolding);\\n }\\n\\n if (totalHoldings != 0) {\\n IERC20(xvs).safeTransfer(recipient, totalHoldings);\\n emit VenusGranted(recipient, totalHoldings);\\n }\\n\\n return totalHoldings;\\n }\\n\\n /**\\n * @notice Claim all xvs accrued by the holders\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\\n */\\n function claimVenus(\\n address[] memory holders,\\n VToken[] memory vTokens,\\n bool borrowers,\\n bool suppliers,\\n bool collateral\\n ) public {\\n uint256 holdersLength = holders.length;\\n\\n updateAndDistributeRewardsInternal(holders, vTokens, borrowers, suppliers);\\n for (uint256 j; j < holdersLength; ++j) {\\n address holder = holders[j];\\n\\n // If there is a positive shortfall, the XVS reward is accrued,\\n // but won't be granted to this holder\\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n holder,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n\\n uint256 value = venusAccrued[holder];\\n delete venusAccrued[holder];\\n\\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\\n\\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\\n if (returnAmount != 0) {\\n venusAccrued[holder] = returnAmount;\\n }\\n }\\n }\\n\\n /**\\n * @notice Update and distribute tokens\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n */\\n function updateAndDistributeRewardsInternal(\\n address[] memory holders,\\n VToken[] memory vTokens,\\n bool borrowers,\\n bool suppliers\\n ) internal {\\n uint256 j;\\n uint256 holdersLength = holders.length;\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n VToken vToken = vTokens[i];\\n ensureListed(getCorePoolMarket(address(vToken)));\\n if (borrowers) {\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n updateVenusBorrowIndex(address(vToken), borrowIndex);\\n for (j = 0; j < holdersLength; ++j) {\\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\\n }\\n }\\n\\n if (suppliers) {\\n updateVenusSupplyIndex(address(vToken));\\n for (j = 0; j < holdersLength; ++j) {\\n distributeSupplierVenus(address(vToken), holders[j]);\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Returns the XVS vToken address\\n * @return The address of XVS vToken\\n */\\n function getXVSVTokenAddress() external view returns (address) {\\n return xvsVToken;\\n }\\n}\\n\",\"keccak256\":\"0x4f41cd1f11452ef2db24d231998158c0af4a0d71f16e24c527c2096bcd58dbea\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\n\\n/**\\n * @title XVSRewardsHelper\\n * @author Venus\\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\\n */\\ncontract XVSRewardsHelper is FacetBase {\\n /// @notice Emitted when XVS is distributed to a borrower\\n event DistributedBorrowerVenus(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 venusDelta,\\n uint256 venusBorrowIndex\\n );\\n\\n /// @notice Emitted when XVS is distributed to a supplier\\n event DistributedSupplierVenus(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 venusDelta,\\n uint256 venusSupplyIndex\\n );\\n\\n /**\\n * @notice Accrue XVS to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n */\\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\\n if (deltaBlocks != 0 && borrowSpeed != 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \\\"224\\\");\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n borrowState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Accrue XVS to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n */\\n function updateVenusSupplyIndex(address vToken) internal {\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n uint256 supplySpeed = venusSupplySpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\\n if (deltaBlocks != 0 && supplySpeed != 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \\\"224\\\");\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n supplyState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute XVS to\\n */\\n function distributeSupplierVenus(address vToken, address supplier) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 supplyIndex = venusSupplyState[vToken].index;\\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\\n // Update supplier's index to the current index since we are distributing accrued XVS\\n venusSupplierIndex[vToken][supplier] = supplyIndex;\\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n // Multiply of supplierTokens and supplierDelta\\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\\n // Addition of supplierAccrued and supplierDelta\\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute XVS to\\n */\\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 borrowIndex = venusBorrowState[vToken].index;\\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\\n // Update borrowers's index to the current index since we are distributing accrued XVS\\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0xf356db714f7aada286380ee5092b0a3e3163428943cfb5561ded76597e1c0c15\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IFacetBase } from \\\"./IFacetBase.sol\\\";\\n\\ninterface IRewardFacet is IFacetBase {\\n function claimVenus(address holder) external;\\n\\n function claimVenus(address holder, VToken[] calldata vTokens) external;\\n\\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\\n\\n function claimVenusAsCollateral(address holder) external;\\n\\n function _grantXVS(address recipient, uint256 amount) external;\\n\\n function getXVSVTokenAddress() external view returns (address);\\n\\n function claimVenus(\\n address[] calldata holders,\\n VToken[] calldata vTokens,\\n bool borrowers,\\n bool suppliers,\\n bool collateral\\n ) external;\\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xdc0657a78bee600d863de3bc6043afca1b6ecb4cd7c4042dc1857e15981a05b5\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b50612abe8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610372575f3560e01c80639254f5e5116101d4578063c5f956af11610109578063e0f6123d116100a9578063ededbae611610079578063ededbae6146108bb578063f445d703146108cc578063f851a440146108f9578063fa6331d81461090b575f80fd5b8063e0f6123d14610846578063e37d4b7914610868578063e85a29601461089f578063e8755446146108b2575f80fd5b8063d3270f99116100e4578063d3270f9914610806578063d463654c14610819578063dce1544914610820578063dcfbc0c714610833575f80fd5b8063c5f956af146107cd578063c7ee005e146107e0578063d09c54ba146107f3575f80fd5b8063b2eafc3911610174578063bbb8864a1161014f578063bbb8864a14610767578063bec04f7214610786578063bf32442d1461078f578063c5b4db55146107a0575f80fd5b8063b2eafc39146106e6578063b8324c7c146106f9578063bb82aa5e14610754575f80fd5b80639bb27d62116101af5780639bb27d621461069a578063a657e579146106ad578063a7604b41146106c0578063adcd5fb9146106d3575f80fd5b80639254f5e51461065c57806394b2294b1461066f57806396c9906414610678575f80fd5b806352d84d1e116102aa5780637858524d1161024a5780637fb8e8cd116102255780637fb8e8cd146105fb57806386df31ee146106085780638a7dc1651461061b5780638c1ac18a1461063a575f80fd5b80637858524d146105c25780637d172bd5146105d55780637dc0d1d0146105e8575f80fd5b806370bf66f01161028557806370bf66f014610552578063719f701b14610567578063737690991461057057806376551383146105b0575f80fd5b806352d84d1e1461050d5780635dd3fc9d14610520578063655f07251461053f575f80fd5b8063267822471161031557806341a18d2c116102f057806341a18d2c1461049e578063425fad58146104c85780634a584432146104db5780634d99c776146104fa575f80fd5b8063267822471461045f5780632bc7e29e146104725780634088c73e14610491575f80fd5b80630db4b4e5116103505780630db4b4e5146103db57806310b98338146103e457806321af45691461042157806324a3d6221461044c575f80fd5b806302c3bcbb1461037657806304ef9d58146103a857806308e0225c146103b1575b5f80fd5b610395610384366004612417565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61039560225481565b6103956103bf366004612432565b601360209081525f928352604080842090915290825290205481565b610395601d5481565b6104116103f2366004612432565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161039f565b601e54610434906001600160a01b031681565b6040516001600160a01b03909116815260200161039f565b600a54610434906001600160a01b031681565b600154610434906001600160a01b031681565b610395610480366004612417565b60166020525f908152604090205481565b6018546104119060ff1681565b6103956104ac366004612432565b601260209081525f928352604080842090915290825290205481565b6018546104119062010000900460ff1681565b6103956104e9366004612417565b601f6020525f908152604090205481565b610395610508366004612484565b610914565b61043461051b36600461249e565b610935565b61039561052e366004612417565b602b6020525f908152604090205481565b61039561054d3660046124b5565b61095d565b610565610560366004612683565b610b65565b005b610395601c5481565b61059861057e366004612417565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161039f565b60185461041190610100900460ff1681565b6105656105d0366004612417565b610c14565b601b54610434906001600160a01b031681565b600454610434906001600160a01b031681565b6039546104119060ff1681565b61056561061636600461271b565b610cd3565b610395610629366004612417565b60146020525f908152604090205481565b610411610648366004612417565b602d6020525f908152604090205460ff1681565b601554610434906001600160a01b031681565b61039560075481565b61068b610686366004612768565b610d39565b60405161039f939291906127af565b602554610434906001600160a01b031681565b603754610598906001600160601b031681565b6105656106ce3660046127d8565b610de6565b6105656106e1366004612417565b610e81565b602054610434906001600160a01b031681565b610730610707366004612417565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161039f565b600254610434906001600160a01b031681565b610395610775366004612417565b602a6020525f908152604090205481565b61039560175481565b6033546001600160a01b0316610434565b6107b56a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b03909116815260200161039f565b602154610434906001600160a01b031681565b603154610434906001600160a01b031681565b610565610801366004612802565b610ee6565b602654610434906001600160a01b031681565b6105985f81565b61043461082e3660046127d8565b610ef9565b600354610434906001600160a01b031681565b610411610854366004612417565b60386020525f908152604090205460ff1681565b610730610876366004612417565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6104116108ad366004612886565b610f2d565b61039560055481565b6034546001600160a01b0316610434565b6104116108da366004612432565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610434906001600160a01b031681565b610395601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d8181548110610944575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f61099c6040518060400160405280601d81526020017f7365697a6556656e757328616464726573735b5d2c6164647265737329000000815250610f71565b604080516020808602828101820190935285825285925f92610a339290918991869182918501908490808284375f9201919091525050600d805460408051602080840282018101909252828152945091925090830182828015610a2657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a08575b505050505060018061101e565b5f5b82811015610af8575f878783818110610a5057610a506128b5565b9050602002016020810190610a659190612417565b6001600160a01b0381165f908152601460205260409020549091508015610aab57610a9081856128dd565b6001600160a01b0383165f9081526014602052604081205593505b816001600160a01b03167fa82ad8dba07d5fde98bd3f0ef9b20c6426de9d477bb7647d46e0c7e50c7dc1b282604051610ae691815260200190565b60405180910390a25050600101610a35565b508015610b5a57603354610b16906001600160a01b03168583611176565b836001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e82604051610b5191815260200190565b60405180910390a25b9150505b9392505050565b8451610b738686868661101e565b5f5b81811015610c0b575f878281518110610b9057610b906128b5565b602002602001015190505f610ba8825f805f806111d9565b6001600160a01b0385165f9081526014602052604081208054908290559194509092509050610bd98483858a611286565b90508015610bfc576001600160a01b0384165f9081526014602052604090208190555b50505050806001019050610b75565b50505050505050565b6040805160018082528183019092525f916020808301908036833701905050905081815f81518110610c4857610c486128b5565b60200260200101906001600160a01b031690816001600160a01b031681525050610ccf81600d805480602002602001604051908101604052809291908181526020018280548015610cc057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ca2575b50505050506001806001610b65565b5050565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610d0757610d076128b5565b60200260200101906001600160a01b031690816001600160a01b031681525050610d348183600180610ee6565b505050565b60366020525f9081526040902080548190610d53906128f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7f906128f0565b8015610dca5780601f10610da157610100808354040283529160200191610dca565b820191905f5260205f20905b815481529060010190602001808311610dad57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b610dee611534565b5f610dfb83835f80611286565b90508015610e395760405162461bcd60e51b81526020600482015260066024820152656e6f2078767360d01b60448201526064015b60405180910390fd5b826001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e83604051610e7491815260200190565b60405180910390a2505050565b610ee381600d805480602002602001604051908101604052809291908181526020018280548015610ed957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ebb575b5050505050610cd3565b50565b610ef3848484845f610b65565b50505050565b6008602052815f5260405f208181548110610f12575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610f5757610f57612928565b815260208101919091526040015f205460ff169392505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90610fa3903390859060040161293c565b602060405180830381865afa158015610fbe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe2919061295f565b610ee35760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e30565b835183515f9190825b8181101561116c575f878281518110611042576110426128b5565b6020026020010151905061105d61105882611580565b6115a2565b861561111a575f6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110cf919061297a565b905290506110dd82826115e7565b5f95505b848610156111185761110d828b88815181106110ff576110ff6128b5565b60200260200101518361177d565b8560010195506110e1565b505b85156111635761112981611901565b5f94505b8385101561116357611158818a878151811061114b5761114b6128b5565b6020026020010151611a6d565b84600101945061112d565b50600101611027565b5050505050505050565b6040516001600160a01b038316602482015260448101829052610d3490849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c0b565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e9061121f9030908f908f908f908f908f90600401612991565b606060405180830381865afa15801561123a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061125e91906129ec565b92509250925082601481111561127657611276612928565b9b919a5098509650505050505050565b5f73ef044206db68e40520bfa82d45419d498b4bc7bf6001600160a01b038616148015906112d15750737589dd3355dae848fdbf75044a3495351655cb1a6001600160a01b03861614155b80156112fa57507333df7a7f6d44307e1e5f3b15975b47515e5524c06001600160a01b03861614155b801561132357507324e77e5b74b30b026e9996e4bc3329c881e249686001600160a01b03861614155b61135d5760405162461bcd60e51b815260206004820152600b60248201526a109b1858dadb1a5cdd195960aa1b6044820152606401610e30565b6033546001600160a01b03168415806113da57506040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113d7919061297a565b85115b156113e8578491505061152c565b835f0361140c576114036001600160a01b0382168787611176565b5f91505061152c565b826114445760405162461bcd60e51b815260206004820152600860248201526718985b9adc9d5c1d60c21b6044820152606401610e30565b6034546001600160a01b0390811690611460908316825f611cde565b6114746001600160a01b0383168288611cde565b5f6040516323323e0360e01b81526001600160a01b038981166004830152602482018990528316906323323e03906044016020604051808303815f875af11580156114c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114e5919061297a565b146115265760405162461bcd60e51b815260206004820152601160248201527036b4b73a103132b430b6331032b93937b960791b6044820152606401610e30565b5f925050505b949350505050565b5f546001600160a01b0316331461157e5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e30565b565b5f60095f61158e5f85610914565b81526020019081526020015f209050919050565b805460ff16610ee35760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e30565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611613611df1565b83549091505f906116349063ffffffff80851691600160e01b900416611e2a565b9050801580159061164457508215155b15611753575f6116b3876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611689573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116ad919061297a565b87611e63565b90505f6116c08386611e80565b90505f825f036116de5760405180602001604052805f8152506116e8565b6116e88284611ec1565b604080516020810190915288546001600160e01b03168152909150611731906117119083611f04565b516040805180820190915260038152620c8c8d60ea1b6020820152611f2d565b6001600160e01b0316600160e01b63ffffffff87160217875550611775915050565b80156117755783546001600160e01b0316600160e01b63ffffffff8416021784555b505050505050565b601b546001600160a01b03161561179657611796611f5b565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b039092169081905590801580156117f257506a0c097ce7bc90715b34b9f160241b8210155b1561180857506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061181e8585611e2a565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f9161187791611871918a16906395dd919390602401602060405180830381865afa158015611689573d5f803e3d5ffd5b836120ea565b6001600160a01b0387165f9081526014602052604090205490915061189c9082612111565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161192d611df1565b83549091505f9061194e9063ffffffff80851691600160e01b900416611e2a565b9050801580159061195e57508215155b15611a44575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119c4919061297a565b90505f6119d18386611e80565b90505f825f036119ef5760405180602001604052805f8152506119f9565b6119f98284611ec1565b604080516020810190915288546001600160e01b03168152909150611a22906117119083611f04565b6001600160e01b0316600160e01b63ffffffff87160217875550611a66915050565b8015611a665783546001600160e01b0316600160e01b63ffffffff8416021784555b5050505050565b601b546001600160a01b031615611a8657611a86611f5b565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b03909216908190559080158015611ae257506a0c097ce7bc90715b34b9f160241b8210155b15611af857506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611b0e8585611e2a565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f91611b8291908816906370a0823190602401602060405180830381865afa158015611b5e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611871919061297a565b6001600160a01b0386165f90815260146020526040902054909150611ba79082612111565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f611c5f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121469092919063ffffffff16565b905080515f1480611c7f575080806020019051810190611c7f919061295f565b610d345760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e30565b801580611d565750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611d30573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d54919061297a565b155b611dc15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e30565b6040516001600160a01b038316602482015260448101829052610d3490849063095ea7b360e01b906064016111a2565b5f611e254360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612154565b905090565b5f610b5e8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061217b565b5f610b5e611e7984670de0b6b3a7640000611e80565b83516121a9565b5f610b5e83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506121db565b60408051602081019091525f81526040518060200160405280611efb611ef5866a0c097ce7bc90715b34b9f160241b611e80565b856121a9565b90529392505050565b60408051602081019091525f81526040518060200160405280611efb855f0151855f0151612111565b5f81600160e01b8410611f535760405162461bcd60e51b8152600401610e309190612a17565b509192915050565b601c541580611f6b5750601c5443105b15611f7257565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015611fbc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe0919061297a565b9050805f03611fed575050565b5f80611ffb43601c54611e2a565b90505f61200a601a5483611e80565b905080841061201b5780925061201f565b8392505b601d54831015612030575050505050565b43601c55601b5461204e906001600160a01b03878116911685611176565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156120cd575f80fd5b505af11580156120df573d5f803e3d5ffd5b505050505050505050565b5f6a0c097ce7bc90715b34b9f160241b61210784845f0151611e80565b610b5e9190612a29565b5f610b5e8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612234565b606061152c84845f85612264565b5f816401000000008410611f535760405162461bcd60e51b8152600401610e309190612a17565b5f818484111561219e5760405162461bcd60e51b8152600401610e309190612a17565b5061152c8385612a48565b5f610b5e83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525061233b565b5f8315806121e7575082155b156121f357505f610b5e565b5f6121fe8486612a5b565b90508361220b8683612a29565b14839061222b5760405162461bcd60e51b8152600401610e309190612a17565b50949350505050565b5f8061224084866128dd565b9050828582101561222b5760405162461bcd60e51b8152600401610e309190612a17565b6060824710156122c55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e30565b5f80866001600160a01b031685876040516122e09190612a72565b5f6040518083038185875af1925050503d805f811461231a576040519150601f19603f3d011682016040523d82523d5f602084013e61231f565b606091505b509150915061233087838387612366565b979650505050505050565b5f818361235b5760405162461bcd60e51b8152600401610e309190612a17565b5061152c8385612a29565b606083156123d45782515f036123cd576001600160a01b0385163b6123cd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e30565b508161152c565b61152c83838151156123e95781518083602001fd5b8060405162461bcd60e51b8152600401610e309190612a17565b6001600160a01b0381168114610ee3575f80fd5b5f60208284031215612427575f80fd5b8135610b5e81612403565b5f8060408385031215612443575f80fd5b823561244e81612403565b9150602083013561245e81612403565b809150509250929050565b80356001600160601b038116811461247f575f80fd5b919050565b5f8060408385031215612495575f80fd5b61244e83612469565b5f602082840312156124ae575f80fd5b5035919050565b5f805f604084860312156124c7575f80fd5b833567ffffffffffffffff808211156124de575f80fd5b818601915086601f8301126124f1575f80fd5b8135818111156124ff575f80fd5b8760208260051b8501011115612513575f80fd5b6020928301955093505084013561252981612403565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561257157612571612534565b604052919050565b5f67ffffffffffffffff82111561259257612592612534565b5060051b60200190565b5f82601f8301126125ab575f80fd5b813560206125c06125bb83612579565b612548565b8083825260208201915060208460051b8701019350868411156125e1575f80fd5b602086015b848110156126065780356125f981612403565b83529183019183016125e6565b509695505050505050565b5f82601f830112612620575f80fd5b813560206126306125bb83612579565b8083825260208201915060208460051b870101935086841115612651575f80fd5b602086015b8481101561260657803561266981612403565b8352918301918301612656565b8015158114610ee3575f80fd5b5f805f805f60a08688031215612697575f80fd5b853567ffffffffffffffff808211156126ae575f80fd5b6126ba89838a0161259c565b965060208801359150808211156126cf575f80fd5b506126dc88828901612611565b94505060408601356126ed81612676565b925060608601356126fd81612676565b9150608086013561270d81612676565b809150509295509295909350565b5f806040838503121561272c575f80fd5b823561273781612403565b9150602083013567ffffffffffffffff811115612752575f80fd5b61275e85828601612611565b9150509250929050565b5f60208284031215612778575f80fd5b610b5e82612469565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6127c16060830186612781565b931515602083015250901515604090910152919050565b5f80604083850312156127e9575f80fd5b82356127f481612403565b946020939093013593505050565b5f805f8060808587031215612815575f80fd5b843567ffffffffffffffff8082111561282c575f80fd5b6128388883890161259c565b9550602087013591508082111561284d575f80fd5b5061285a87828801612611565b935050604085013561286b81612676565b9150606085013561287b81612676565b939692955090935050565b5f8060408385031215612897575f80fd5b82356128a281612403565b915060208301356009811061245e575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561092f5761092f6128c9565b600181811c9082168061290457607f821691505b60208210810361292257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040602082018190525f9061152c90830184612781565b5f6020828403121561296f575f80fd5b8151610b5e81612676565b5f6020828403121561298a575f80fd5b5051919050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101600283106129db57634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f606084860312156129fe575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610b5e6020830184612781565b5f82612a4357634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561092f5761092f6128c9565b808202811582820484141761092f5761092f6128c9565b5f82518060208501845e5f92019182525091905056fea264697066735822122017d59e4712f7786caae56c195ab5a337020d4fb0e25480df676cefb75874181464736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610372575f3560e01c80639254f5e5116101d4578063c5f956af11610109578063e0f6123d116100a9578063ededbae611610079578063ededbae6146108bb578063f445d703146108cc578063f851a440146108f9578063fa6331d81461090b575f80fd5b8063e0f6123d14610846578063e37d4b7914610868578063e85a29601461089f578063e8755446146108b2575f80fd5b8063d3270f99116100e4578063d3270f9914610806578063d463654c14610819578063dce1544914610820578063dcfbc0c714610833575f80fd5b8063c5f956af146107cd578063c7ee005e146107e0578063d09c54ba146107f3575f80fd5b8063b2eafc3911610174578063bbb8864a1161014f578063bbb8864a14610767578063bec04f7214610786578063bf32442d1461078f578063c5b4db55146107a0575f80fd5b8063b2eafc39146106e6578063b8324c7c146106f9578063bb82aa5e14610754575f80fd5b80639bb27d62116101af5780639bb27d621461069a578063a657e579146106ad578063a7604b41146106c0578063adcd5fb9146106d3575f80fd5b80639254f5e51461065c57806394b2294b1461066f57806396c9906414610678575f80fd5b806352d84d1e116102aa5780637858524d1161024a5780637fb8e8cd116102255780637fb8e8cd146105fb57806386df31ee146106085780638a7dc1651461061b5780638c1ac18a1461063a575f80fd5b80637858524d146105c25780637d172bd5146105d55780637dc0d1d0146105e8575f80fd5b806370bf66f01161028557806370bf66f014610552578063719f701b14610567578063737690991461057057806376551383146105b0575f80fd5b806352d84d1e1461050d5780635dd3fc9d14610520578063655f07251461053f575f80fd5b8063267822471161031557806341a18d2c116102f057806341a18d2c1461049e578063425fad58146104c85780634a584432146104db5780634d99c776146104fa575f80fd5b8063267822471461045f5780632bc7e29e146104725780634088c73e14610491575f80fd5b80630db4b4e5116103505780630db4b4e5146103db57806310b98338146103e457806321af45691461042157806324a3d6221461044c575f80fd5b806302c3bcbb1461037657806304ef9d58146103a857806308e0225c146103b1575b5f80fd5b610395610384366004612417565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61039560225481565b6103956103bf366004612432565b601360209081525f928352604080842090915290825290205481565b610395601d5481565b6104116103f2366004612432565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161039f565b601e54610434906001600160a01b031681565b6040516001600160a01b03909116815260200161039f565b600a54610434906001600160a01b031681565b600154610434906001600160a01b031681565b610395610480366004612417565b60166020525f908152604090205481565b6018546104119060ff1681565b6103956104ac366004612432565b601260209081525f928352604080842090915290825290205481565b6018546104119062010000900460ff1681565b6103956104e9366004612417565b601f6020525f908152604090205481565b610395610508366004612484565b610914565b61043461051b36600461249e565b610935565b61039561052e366004612417565b602b6020525f908152604090205481565b61039561054d3660046124b5565b61095d565b610565610560366004612683565b610b65565b005b610395601c5481565b61059861057e366004612417565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161039f565b60185461041190610100900460ff1681565b6105656105d0366004612417565b610c14565b601b54610434906001600160a01b031681565b600454610434906001600160a01b031681565b6039546104119060ff1681565b61056561061636600461271b565b610cd3565b610395610629366004612417565b60146020525f908152604090205481565b610411610648366004612417565b602d6020525f908152604090205460ff1681565b601554610434906001600160a01b031681565b61039560075481565b61068b610686366004612768565b610d39565b60405161039f939291906127af565b602554610434906001600160a01b031681565b603754610598906001600160601b031681565b6105656106ce3660046127d8565b610de6565b6105656106e1366004612417565b610e81565b602054610434906001600160a01b031681565b610730610707366004612417565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161039f565b600254610434906001600160a01b031681565b610395610775366004612417565b602a6020525f908152604090205481565b61039560175481565b6033546001600160a01b0316610434565b6107b56a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b03909116815260200161039f565b602154610434906001600160a01b031681565b603154610434906001600160a01b031681565b610565610801366004612802565b610ee6565b602654610434906001600160a01b031681565b6105985f81565b61043461082e3660046127d8565b610ef9565b600354610434906001600160a01b031681565b610411610854366004612417565b60386020525f908152604090205460ff1681565b610730610876366004612417565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6104116108ad366004612886565b610f2d565b61039560055481565b6034546001600160a01b0316610434565b6104116108da366004612432565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610434906001600160a01b031681565b610395601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d8181548110610944575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f61099c6040518060400160405280601d81526020017f7365697a6556656e757328616464726573735b5d2c6164647265737329000000815250610f71565b604080516020808602828101820190935285825285925f92610a339290918991869182918501908490808284375f9201919091525050600d805460408051602080840282018101909252828152945091925090830182828015610a2657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a08575b505050505060018061101e565b5f5b82811015610af8575f878783818110610a5057610a506128b5565b9050602002016020810190610a659190612417565b6001600160a01b0381165f908152601460205260409020549091508015610aab57610a9081856128dd565b6001600160a01b0383165f9081526014602052604081205593505b816001600160a01b03167fa82ad8dba07d5fde98bd3f0ef9b20c6426de9d477bb7647d46e0c7e50c7dc1b282604051610ae691815260200190565b60405180910390a25050600101610a35565b508015610b5a57603354610b16906001600160a01b03168583611176565b836001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e82604051610b5191815260200190565b60405180910390a25b9150505b9392505050565b8451610b738686868661101e565b5f5b81811015610c0b575f878281518110610b9057610b906128b5565b602002602001015190505f610ba8825f805f806111d9565b6001600160a01b0385165f9081526014602052604081208054908290559194509092509050610bd98483858a611286565b90508015610bfc576001600160a01b0384165f9081526014602052604090208190555b50505050806001019050610b75565b50505050505050565b6040805160018082528183019092525f916020808301908036833701905050905081815f81518110610c4857610c486128b5565b60200260200101906001600160a01b031690816001600160a01b031681525050610ccf81600d805480602002602001604051908101604052809291908181526020018280548015610cc057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ca2575b50505050506001806001610b65565b5050565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610d0757610d076128b5565b60200260200101906001600160a01b031690816001600160a01b031681525050610d348183600180610ee6565b505050565b60366020525f9081526040902080548190610d53906128f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7f906128f0565b8015610dca5780601f10610da157610100808354040283529160200191610dca565b820191905f5260205f20905b815481529060010190602001808311610dad57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b610dee611534565b5f610dfb83835f80611286565b90508015610e395760405162461bcd60e51b81526020600482015260066024820152656e6f2078767360d01b60448201526064015b60405180910390fd5b826001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e83604051610e7491815260200190565b60405180910390a2505050565b610ee381600d805480602002602001604051908101604052809291908181526020018280548015610ed957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ebb575b5050505050610cd3565b50565b610ef3848484845f610b65565b50505050565b6008602052815f5260405f208181548110610f12575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610f5757610f57612928565b815260208101919091526040015f205460ff169392505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90610fa3903390859060040161293c565b602060405180830381865afa158015610fbe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe2919061295f565b610ee35760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e30565b835183515f9190825b8181101561116c575f878281518110611042576110426128b5565b6020026020010151905061105d61105882611580565b6115a2565b861561111a575f6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110cf919061297a565b905290506110dd82826115e7565b5f95505b848610156111185761110d828b88815181106110ff576110ff6128b5565b60200260200101518361177d565b8560010195506110e1565b505b85156111635761112981611901565b5f94505b8385101561116357611158818a878151811061114b5761114b6128b5565b6020026020010151611a6d565b84600101945061112d565b50600101611027565b5050505050505050565b6040516001600160a01b038316602482015260448101829052610d3490849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c0b565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e9061121f9030908f908f908f908f908f90600401612991565b606060405180830381865afa15801561123a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061125e91906129ec565b92509250925082601481111561127657611276612928565b9b919a5098509650505050505050565b5f73ef044206db68e40520bfa82d45419d498b4bc7bf6001600160a01b038616148015906112d15750737589dd3355dae848fdbf75044a3495351655cb1a6001600160a01b03861614155b80156112fa57507333df7a7f6d44307e1e5f3b15975b47515e5524c06001600160a01b03861614155b801561132357507324e77e5b74b30b026e9996e4bc3329c881e249686001600160a01b03861614155b61135d5760405162461bcd60e51b815260206004820152600b60248201526a109b1858dadb1a5cdd195960aa1b6044820152606401610e30565b6033546001600160a01b03168415806113da57506040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113d7919061297a565b85115b156113e8578491505061152c565b835f0361140c576114036001600160a01b0382168787611176565b5f91505061152c565b826114445760405162461bcd60e51b815260206004820152600860248201526718985b9adc9d5c1d60c21b6044820152606401610e30565b6034546001600160a01b0390811690611460908316825f611cde565b6114746001600160a01b0383168288611cde565b5f6040516323323e0360e01b81526001600160a01b038981166004830152602482018990528316906323323e03906044016020604051808303815f875af11580156114c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114e5919061297a565b146115265760405162461bcd60e51b815260206004820152601160248201527036b4b73a103132b430b6331032b93937b960791b6044820152606401610e30565b5f925050505b949350505050565b5f546001600160a01b0316331461157e5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e30565b565b5f60095f61158e5f85610914565b81526020019081526020015f209050919050565b805460ff16610ee35760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e30565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611613611df1565b83549091505f906116349063ffffffff80851691600160e01b900416611e2a565b9050801580159061164457508215155b15611753575f6116b3876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611689573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116ad919061297a565b87611e63565b90505f6116c08386611e80565b90505f825f036116de5760405180602001604052805f8152506116e8565b6116e88284611ec1565b604080516020810190915288546001600160e01b03168152909150611731906117119083611f04565b516040805180820190915260038152620c8c8d60ea1b6020820152611f2d565b6001600160e01b0316600160e01b63ffffffff87160217875550611775915050565b80156117755783546001600160e01b0316600160e01b63ffffffff8416021784555b505050505050565b601b546001600160a01b03161561179657611796611f5b565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b039092169081905590801580156117f257506a0c097ce7bc90715b34b9f160241b8210155b1561180857506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061181e8585611e2a565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f9161187791611871918a16906395dd919390602401602060405180830381865afa158015611689573d5f803e3d5ffd5b836120ea565b6001600160a01b0387165f9081526014602052604090205490915061189c9082612111565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161192d611df1565b83549091505f9061194e9063ffffffff80851691600160e01b900416611e2a565b9050801580159061195e57508215155b15611a44575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119c4919061297a565b90505f6119d18386611e80565b90505f825f036119ef5760405180602001604052805f8152506119f9565b6119f98284611ec1565b604080516020810190915288546001600160e01b03168152909150611a22906117119083611f04565b6001600160e01b0316600160e01b63ffffffff87160217875550611a66915050565b8015611a665783546001600160e01b0316600160e01b63ffffffff8416021784555b5050505050565b601b546001600160a01b031615611a8657611a86611f5b565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b03909216908190559080158015611ae257506a0c097ce7bc90715b34b9f160241b8210155b15611af857506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611b0e8585611e2a565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f91611b8291908816906370a0823190602401602060405180830381865afa158015611b5e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611871919061297a565b6001600160a01b0386165f90815260146020526040902054909150611ba79082612111565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f611c5f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121469092919063ffffffff16565b905080515f1480611c7f575080806020019051810190611c7f919061295f565b610d345760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e30565b801580611d565750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611d30573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d54919061297a565b155b611dc15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e30565b6040516001600160a01b038316602482015260448101829052610d3490849063095ea7b360e01b906064016111a2565b5f611e254360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612154565b905090565b5f610b5e8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061217b565b5f610b5e611e7984670de0b6b3a7640000611e80565b83516121a9565b5f610b5e83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506121db565b60408051602081019091525f81526040518060200160405280611efb611ef5866a0c097ce7bc90715b34b9f160241b611e80565b856121a9565b90529392505050565b60408051602081019091525f81526040518060200160405280611efb855f0151855f0151612111565b5f81600160e01b8410611f535760405162461bcd60e51b8152600401610e309190612a17565b509192915050565b601c541580611f6b5750601c5443105b15611f7257565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015611fbc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe0919061297a565b9050805f03611fed575050565b5f80611ffb43601c54611e2a565b90505f61200a601a5483611e80565b905080841061201b5780925061201f565b8392505b601d54831015612030575050505050565b43601c55601b5461204e906001600160a01b03878116911685611176565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156120cd575f80fd5b505af11580156120df573d5f803e3d5ffd5b505050505050505050565b5f6a0c097ce7bc90715b34b9f160241b61210784845f0151611e80565b610b5e9190612a29565b5f610b5e8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612234565b606061152c84845f85612264565b5f816401000000008410611f535760405162461bcd60e51b8152600401610e309190612a17565b5f818484111561219e5760405162461bcd60e51b8152600401610e309190612a17565b5061152c8385612a48565b5f610b5e83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525061233b565b5f8315806121e7575082155b156121f357505f610b5e565b5f6121fe8486612a5b565b90508361220b8683612a29565b14839061222b5760405162461bcd60e51b8152600401610e309190612a17565b50949350505050565b5f8061224084866128dd565b9050828582101561222b5760405162461bcd60e51b8152600401610e309190612a17565b6060824710156122c55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e30565b5f80866001600160a01b031685876040516122e09190612a72565b5f6040518083038185875af1925050503d805f811461231a576040519150601f19603f3d011682016040523d82523d5f602084013e61231f565b606091505b509150915061233087838387612366565b979650505050505050565b5f818361235b5760405162461bcd60e51b8152600401610e309190612a17565b5061152c8385612a29565b606083156123d45782515f036123cd576001600160a01b0385163b6123cd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e30565b508161152c565b61152c83838151156123e95781518083602001fd5b8060405162461bcd60e51b8152600401610e309190612a17565b6001600160a01b0381168114610ee3575f80fd5b5f60208284031215612427575f80fd5b8135610b5e81612403565b5f8060408385031215612443575f80fd5b823561244e81612403565b9150602083013561245e81612403565b809150509250929050565b80356001600160601b038116811461247f575f80fd5b919050565b5f8060408385031215612495575f80fd5b61244e83612469565b5f602082840312156124ae575f80fd5b5035919050565b5f805f604084860312156124c7575f80fd5b833567ffffffffffffffff808211156124de575f80fd5b818601915086601f8301126124f1575f80fd5b8135818111156124ff575f80fd5b8760208260051b8501011115612513575f80fd5b6020928301955093505084013561252981612403565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561257157612571612534565b604052919050565b5f67ffffffffffffffff82111561259257612592612534565b5060051b60200190565b5f82601f8301126125ab575f80fd5b813560206125c06125bb83612579565b612548565b8083825260208201915060208460051b8701019350868411156125e1575f80fd5b602086015b848110156126065780356125f981612403565b83529183019183016125e6565b509695505050505050565b5f82601f830112612620575f80fd5b813560206126306125bb83612579565b8083825260208201915060208460051b870101935086841115612651575f80fd5b602086015b8481101561260657803561266981612403565b8352918301918301612656565b8015158114610ee3575f80fd5b5f805f805f60a08688031215612697575f80fd5b853567ffffffffffffffff808211156126ae575f80fd5b6126ba89838a0161259c565b965060208801359150808211156126cf575f80fd5b506126dc88828901612611565b94505060408601356126ed81612676565b925060608601356126fd81612676565b9150608086013561270d81612676565b809150509295509295909350565b5f806040838503121561272c575f80fd5b823561273781612403565b9150602083013567ffffffffffffffff811115612752575f80fd5b61275e85828601612611565b9150509250929050565b5f60208284031215612778575f80fd5b610b5e82612469565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6127c16060830186612781565b931515602083015250901515604090910152919050565b5f80604083850312156127e9575f80fd5b82356127f481612403565b946020939093013593505050565b5f805f8060808587031215612815575f80fd5b843567ffffffffffffffff8082111561282c575f80fd5b6128388883890161259c565b9550602087013591508082111561284d575f80fd5b5061285a87828801612611565b935050604085013561286b81612676565b9150606085013561287b81612676565b939692955090935050565b5f8060408385031215612897575f80fd5b82356128a281612403565b915060208301356009811061245e575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561092f5761092f6128c9565b600181811c9082168061290457607f821691505b60208210810361292257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040602082018190525f9061152c90830184612781565b5f6020828403121561296f575f80fd5b8151610b5e81612676565b5f6020828403121561298a575f80fd5b5051919050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101600283106129db57634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f606084860312156129fe575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610b5e6020830184612781565b5f82612a4357634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561092f5761092f6128c9565b808202811582820484141761092f5761092f6128c9565b5f82518060208501845e5f92019182525091905056fea264697066735822122017d59e4712f7786caae56c195ab5a337020d4fb0e25480df676cefb75874181464736f6c63430008190033", + "numDeployments": 5, + "solcInputHash": "cbc4287e135101fe4c78448d0f5f2ecc", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"VenusGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"VenusSeized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantXVS\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"collateral\",\"type\":\"bool\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimVenusAsCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSVTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"seizeVenus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the methods related to the reward functionality\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_grantXVS(address,uint256)\":{\"details\":\"Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall Note: If there is not enough XVS, we do not perform the transfer all\",\"params\":{\"amount\":\"The amount of XVS to (possibly) transfer\",\"recipient\":\"The address of the recipient to transfer XVS to\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"claimVenus(address)\":{\"params\":{\"holder\":\"The address to claim XVS for\"}},\"claimVenus(address,address[])\":{\"params\":{\"holder\":\"The address to claim XVS for\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenus(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim XVS earned by borrowing\",\"holders\":\"The addresses to claim XVS for\",\"suppliers\":\"Whether or not to claim XVS earned by supplying\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenus(address[],address[],bool,bool,bool)\":{\"details\":\"The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices. When DBO protection mode is active, a holder with a position that is healthy at spot prices may still show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO.\",\"params\":{\"borrowers\":\"Whether or not to claim XVS earned by borrowing\",\"collateral\":\"Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\",\"holders\":\"The addresses to claim XVS for\",\"suppliers\":\"Whether or not to claim XVS earned by supplying\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenusAsCollateral(address)\":{\"params\":{\"holder\":\"The address to claim XVS for\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"getXVSVTokenAddress()\":{\"returns\":{\"_0\":\"The address of XVS vToken\"}},\"seizeVenus(address[],address)\":{\"details\":\"Seize XVS tokens from the specified holders and transfer to recipient\",\"params\":{\"holders\":\"Addresses of the XVS holders\",\"recipient\":\"Address of the XVS token recipient\"},\"returns\":{\"_0\":\"The total amount of XVS tokens seized and transferred to recipient\"}}},\"title\":\"RewardFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedBorrowerVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a borrower\"},\"DistributedSupplierVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a supplier\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"VenusGranted(address,uint256)\":{\"notice\":\"Emitted when Venus is granted by admin\"},\"VenusSeized(address,uint256)\":{\"notice\":\"Emitted when XVS are seized for the holder\"}},\"kind\":\"user\",\"methods\":{\"_grantXVS(address,uint256)\":{\"notice\":\"Transfer XVS to the recipient\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"claimVenus(address)\":{\"notice\":\"Claim all the xvs accrued by holder in all markets and VAI\"},\"claimVenus(address,address[])\":{\"notice\":\"Claim all the xvs accrued by holder in the specified markets\"},\"claimVenus(address[],address[],bool,bool)\":{\"notice\":\"Claim all xvs accrued by the holders\"},\"claimVenus(address[],address[],bool,bool,bool)\":{\"notice\":\"Claim all xvs accrued by the holders\"},\"claimVenusAsCollateral(address)\":{\"notice\":\"Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"getXVSVTokenAddress()\":{\"notice\":\"Returns the XVS vToken address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"seizeVenus(address[],address)\":{\"notice\":\"Seize XVS rewards allocated to holders\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract provides the external functions related to all claims and rewards of the protocol\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/RewardFacet.sol\":\"RewardFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\\n enum KeeperAction {\\n SetMinPrice,\\n SetMaxPrice,\\n ExitProtectionMode\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool cachingEnabled;\\n }\\n\\n /// @notice One item in an syncPriceBoundsAndProtections payload\\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\\n struct KeeperActionItem {\\n address asset;\\n KeeperAction action;\\n uint256 value;\\n }\\n\\n /// @notice One item in a setTokenConfigs payload\\n struct TokenConfigInput {\\n /// @notice The underlying asset address\\n address asset;\\n /// @notice Minimum time protection stays active after the last trigger (seconds)\\n uint64 cooldownPeriod;\\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\\n uint256 triggerThreshold;\\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\\n uint256 resetThreshold;\\n /// @notice Whether to enable bounded pricing immediately upon initialization\\n bool enableBoundedPricing;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool enableCaching;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n /// @notice Emitted when the per-asset transient caching flag is toggled\\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\\n error InvalidKeeperAction(uint8 action);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage. The transient\\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n /**\\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\\n * Empty `actions` is a no-op success.\\n * @param actions The list of keeper actions to apply\\n * @custom:access Only authorized keeper addresses\\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\\n */\\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param tokenConfig_ Token config input for the asset\\n * @custom:access Only Governance\\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param tokenConfigs_ Array of token config inputs, one per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if the input array is empty\\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\\n * @custom:error VAINotAllowed if any asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n /**\\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\\n * live spot instead of reading or writing the transient slots. The initial value is\\n * set via the `enableCaching` argument of `setTokenConfig`.\\n * @param asset The underlying asset address\\n * @param enabled Whether transient caching is enabled for this asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CachingEnabledUpdated\\n */\\n function setCachingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold,\\n bool cachingEnabled\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0xe223d88c17c0d752fdb33fa223b63ce124a798512f3d69f3800e9508e7dff931\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/RewardFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { IRewardFacet } from \\\"../interfaces/IRewardFacet.sol\\\";\\nimport { XVSRewardsHelper } from \\\"./XVSRewardsHelper.sol\\\";\\nimport { VBep20Interface } from \\\"../../../Tokens/VTokens/VTokenInterfaces.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title RewardFacet\\n * @author Venus\\n * @dev This facet contains all the methods related to the reward functionality\\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\\n */\\ncontract RewardFacet is IRewardFacet, XVSRewardsHelper {\\n /// @notice Emitted when Venus is granted by admin\\n event VenusGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when XVS are seized for the holder\\n event VenusSeized(address indexed holder, uint256 amount);\\n\\n using SafeERC20 for IERC20;\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in all markets and VAI\\n * @param holder The address to claim XVS for\\n */\\n function claimVenus(address holder) public {\\n return claimVenus(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in the specified markets\\n * @param holder The address to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n */\\n function claimVenus(address holder, VToken[] memory vTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimVenus(holders, vTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all xvs accrued by the holders\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n */\\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\\n claimVenus(holders, vTokens, borrowers, suppliers, false);\\n }\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\\n * @param holder The address to claim XVS for\\n */\\n function claimVenusAsCollateral(address holder) external {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimVenus(holders, allMarkets, true, true, true);\\n }\\n\\n /**\\n * @notice Transfer XVS to the user with user's shortfall considered\\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\\n * @param user The address of the user to transfer XVS to\\n * @param amount The amount of XVS to (possibly) transfer\\n * @param shortfall The shortfall of the user\\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\\n * @return The amount of XVS which was NOT transferred to the user\\n */\\n function grantXVSInternal(\\n address user,\\n uint256 amount,\\n uint256 shortfall,\\n bool collateral\\n ) internal returns (uint256) {\\n // If the user is blacklisted, they can't get XVS rewards\\n require(\\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\\n \\\"Blacklisted\\\"\\n );\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n if (amount == 0 || amount > xvs_.balanceOf(address(this))) {\\n return amount;\\n }\\n\\n if (shortfall == 0) {\\n xvs_.safeTransfer(user, amount);\\n return 0;\\n }\\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\\n // anything, otherwise, we will transfer the pending xvs as collateral to\\n // vXVS token and mint vXVS for the user\\n //\\n // If mintBehalf failed, don't grant any xvs\\n require(collateral, \\\"bankrupt\\\");\\n\\n address xvsVToken_ = xvsVToken;\\n\\n xvs_.safeApprove(xvsVToken_, 0);\\n xvs_.safeApprove(xvsVToken_, amount);\\n require(VBep20Interface(xvsVToken_).mintBehalf(user, amount) == uint256(Error.NO_ERROR), \\\"mint behalf error\\\");\\n\\n // set venusAccrued[user] to 0\\n return 0;\\n }\\n\\n /*** Venus Distribution Admin ***/\\n\\n /**\\n * @notice Transfer XVS to the recipient\\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\\n * Note: If there is not enough XVS, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer XVS to\\n * @param amount The amount of XVS to (possibly) transfer\\n */\\n function _grantXVS(address recipient, uint256 amount) external {\\n ensureAdmin();\\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\\n require(amountLeft == 0, \\\"no xvs\\\");\\n emit VenusGranted(recipient, amount);\\n }\\n\\n /**\\n * @dev Seize XVS tokens from the specified holders and transfer to recipient\\n * @notice Seize XVS rewards allocated to holders\\n * @param holders Addresses of the XVS holders\\n * @param recipient Address of the XVS token recipient\\n * @return The total amount of XVS tokens seized and transferred to recipient\\n */\\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256) {\\n ensureAllowed(\\\"seizeVenus(address[],address)\\\");\\n\\n uint256 holdersLength = holders.length;\\n uint256 totalHoldings;\\n\\n updateAndDistributeRewardsInternal(holders, allMarkets, true, true);\\n for (uint256 j; j < holdersLength; ++j) {\\n address holder = holders[j];\\n uint256 userHolding = venusAccrued[holder];\\n\\n if (userHolding != 0) {\\n totalHoldings += userHolding;\\n delete venusAccrued[holder];\\n }\\n\\n emit VenusSeized(holder, userHolding);\\n }\\n\\n if (totalHoldings != 0) {\\n IERC20(xvs).safeTransfer(recipient, totalHoldings);\\n emit VenusGranted(recipient, totalHoldings);\\n }\\n\\n return totalHoldings;\\n }\\n\\n /**\\n * @notice Claim all xvs accrued by the holders\\n * @dev The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices.\\n * When DBO protection mode is active, a holder with a position that is healthy at spot prices may still\\n * show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when\\n * `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO.\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\\n */\\n function claimVenus(\\n address[] memory holders,\\n VToken[] memory vTokens,\\n bool borrowers,\\n bool suppliers,\\n bool collateral\\n ) public {\\n uint256 holdersLength = holders.length;\\n\\n updateAndDistributeRewardsInternal(holders, vTokens, borrowers, suppliers);\\n for (uint256 j; j < holdersLength; ++j) {\\n address holder = holders[j];\\n\\n // If there is a positive shortfall, the XVS reward is accrued,\\n // but won't be granted to this holder\\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n holder,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n\\n uint256 value = venusAccrued[holder];\\n delete venusAccrued[holder];\\n\\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\\n\\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\\n if (returnAmount != 0) {\\n venusAccrued[holder] = returnAmount;\\n }\\n }\\n }\\n\\n /**\\n * @notice Update and distribute tokens\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n */\\n function updateAndDistributeRewardsInternal(\\n address[] memory holders,\\n VToken[] memory vTokens,\\n bool borrowers,\\n bool suppliers\\n ) internal {\\n uint256 j;\\n uint256 holdersLength = holders.length;\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n VToken vToken = vTokens[i];\\n ensureListed(getCorePoolMarket(address(vToken)));\\n if (borrowers) {\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n updateVenusBorrowIndex(address(vToken), borrowIndex);\\n for (j = 0; j < holdersLength; ++j) {\\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\\n }\\n }\\n\\n if (suppliers) {\\n updateVenusSupplyIndex(address(vToken));\\n for (j = 0; j < holdersLength; ++j) {\\n distributeSupplierVenus(address(vToken), holders[j]);\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Returns the XVS vToken address\\n * @return The address of XVS vToken\\n */\\n function getXVSVTokenAddress() external view returns (address) {\\n return xvsVToken;\\n }\\n}\\n\",\"keccak256\":\"0xa8406d304c6fd65150a72a108d6a9ecee8e9a921d01862c76aaa9da6b91fd937\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\n\\n/**\\n * @title XVSRewardsHelper\\n * @author Venus\\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\\n */\\ncontract XVSRewardsHelper is FacetBase {\\n /// @notice Emitted when XVS is distributed to a borrower\\n event DistributedBorrowerVenus(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 venusDelta,\\n uint256 venusBorrowIndex\\n );\\n\\n /// @notice Emitted when XVS is distributed to a supplier\\n event DistributedSupplierVenus(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 venusDelta,\\n uint256 venusSupplyIndex\\n );\\n\\n /**\\n * @notice Accrue XVS to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n */\\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\\n if (deltaBlocks != 0 && borrowSpeed != 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \\\"224\\\");\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n borrowState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Accrue XVS to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n */\\n function updateVenusSupplyIndex(address vToken) internal {\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n uint256 supplySpeed = venusSupplySpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\\n if (deltaBlocks != 0 && supplySpeed != 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \\\"224\\\");\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n supplyState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute XVS to\\n */\\n function distributeSupplierVenus(address vToken, address supplier) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 supplyIndex = venusSupplyState[vToken].index;\\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\\n // Update supplier's index to the current index since we are distributing accrued XVS\\n venusSupplierIndex[vToken][supplier] = supplyIndex;\\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n // Multiply of supplierTokens and supplierDelta\\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\\n // Addition of supplierAccrued and supplierDelta\\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute XVS to\\n */\\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 borrowIndex = venusBorrowState[vToken].index;\\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\\n // Update borrowers's index to the current index since we are distributing accrued XVS\\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0xf356db714f7aada286380ee5092b0a3e3163428943cfb5561ded76597e1c0c15\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IRewardFacet {\\n function claimVenus(address holder) external;\\n\\n function claimVenus(address holder, VToken[] calldata vTokens) external;\\n\\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\\n\\n function claimVenusAsCollateral(address holder) external;\\n\\n function _grantXVS(address recipient, uint256 amount) external;\\n\\n function getXVSVTokenAddress() external view returns (address);\\n\\n function claimVenus(\\n address[] calldata holders,\\n VToken[] calldata vTokens,\\n bool borrowers,\\n bool suppliers,\\n bool collateral\\n ) external;\\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xf3672712ba16df092f162b4bcf3cf02a7c1ae6af142a946c9b93af3cdd1cd8f1\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b50612c148061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061037d575f3560e01c806394b2294b116101d4578063c7ee005e11610109578063e0f6123d116100a9578063ededbae611610079578063ededbae6146108de578063f445d703146108ef578063f851a4401461091c578063fa6331d81461092e575f80fd5b8063e0f6123d14610869578063e37d4b791461088b578063e85a2960146108c2578063e8755446146108d5575f80fd5b8063d463654c116100e4578063d463654c14610824578063d7c46d2d1461082b578063dce1544914610843578063dcfbc0c714610856575f80fd5b8063c7ee005e146107eb578063d09c54ba146107fe578063d3270f9914610811575f80fd5b8063b8324c7c11610174578063bec04f721161014f578063bec04f7214610791578063bf32442d1461079a578063c5b4db55146107ab578063c5f956af146107d8575f80fd5b8063b8324c7c14610704578063bb82aa5e1461075f578063bbb8864a14610772575f80fd5b8063a657e579116101af578063a657e579146106b8578063a7604b41146106cb578063adcd5fb9146106de578063b2eafc39146106f1575f80fd5b806394b2294b1461067a57806396c99064146106835780639bb27d62146106a5575f80fd5b806352d84d1e116102b55780637858524d1161025557806386df31ee1161022557806386df31ee146106135780638a7dc165146106265780638c1ac18a146106455780639254f5e514610667575f80fd5b80637858524d146105cd5780637d172bd5146105e05780637dc0d1d0146105f35780637fb8e8cd14610606575f80fd5b806370bf66f01161029057806370bf66f01461055d578063719f701b14610572578063737690991461057b57806376551383146105bb575f80fd5b806352d84d1e146105185780635dd3fc9d1461052b578063655f07251461054a575f80fd5b8063267822471161032057806341a18d2c116102fb57806341a18d2c146104a9578063425fad58146104d35780634a584432146104e65780634d99c77614610505575f80fd5b8063267822471461046a5780632bc7e29e1461047d5780634088c73e1461049c575f80fd5b80630db4b4e51161035b5780630db4b4e5146103e657806310b98338146103ef57806321af45691461042c57806324a3d62214610457575f80fd5b806302c3bcbb1461038157806304ef9d58146103b357806308e0225c146103bc575b5f80fd5b6103a061038f36600461256d565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103a060225481565b6103a06103ca366004612588565b601360209081525f928352604080842090915290825290205481565b6103a0601d5481565b61041c6103fd366004612588565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103aa565b601e5461043f906001600160a01b031681565b6040516001600160a01b0390911681526020016103aa565b600a5461043f906001600160a01b031681565b60015461043f906001600160a01b031681565b6103a061048b36600461256d565b60166020525f908152604090205481565b60185461041c9060ff1681565b6103a06104b7366004612588565b601260209081525f928352604080842090915290825290205481565b60185461041c9062010000900460ff1681565b6103a06104f436600461256d565b601f6020525f908152604090205481565b6103a06105133660046125da565b610937565b61043f6105263660046125f4565b610958565b6103a061053936600461256d565b602b6020525f908152604090205481565b6103a061055836600461260b565b610980565b61057061056b3660046127d9565b610b88565b005b6103a0601c5481565b6105a361058936600461256d565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103aa565b60185461041c90610100900460ff1681565b6105706105db36600461256d565b610c37565b601b5461043f906001600160a01b031681565b60045461043f906001600160a01b031681565b60395461041c9060ff1681565b610570610621366004612871565b610cf6565b6103a061063436600461256d565b60146020525f908152604090205481565b61041c61065336600461256d565b602d6020525f908152604090205460ff1681565b60155461043f906001600160a01b031681565b6103a060075481565b6106966106913660046128be565b610d5c565b6040516103aa93929190612905565b60255461043f906001600160a01b031681565b6037546105a3906001600160601b031681565b6105706106d936600461292e565b610e09565b6105706106ec36600461256d565b610ea4565b60205461043f906001600160a01b031681565b61073b61071236600461256d565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103aa565b60025461043f906001600160a01b031681565b6103a061078036600461256d565b602a6020525f908152604090205481565b6103a060175481565b6033546001600160a01b031661043f565b6107c06a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020016103aa565b60215461043f906001600160a01b031681565b60315461043f906001600160a01b031681565b61057061080c366004612958565b610f09565b60265461043f906001600160a01b031681565b6105a35f81565b60395461043f9061010090046001600160a01b031681565b61043f61085136600461292e565b610f1c565b60035461043f906001600160a01b031681565b61041c61087736600461256d565b60386020525f908152604090205460ff1681565b61073b61089936600461256d565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61041c6108d03660046129dc565b610f50565b6103a060055481565b6034546001600160a01b031661043f565b61041c6108fd366004612588565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461043f906001600160a01b031681565b6103a0601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d8181548110610967575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f6109bf6040518060400160405280601d81526020017f7365697a6556656e757328616464726573735b5d2c6164647265737329000000815250610f94565b604080516020808602828101820190935285825285925f92610a569290918991869182918501908490808284375f9201919091525050600d805460408051602080840282018101909252828152945091925090830182828015610a4957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a2b575b5050505050600180611041565b5f5b82811015610b1b575f878783818110610a7357610a73612a0b565b9050602002016020810190610a88919061256d565b6001600160a01b0381165f908152601460205260409020549091508015610ace57610ab38185612a33565b6001600160a01b0383165f9081526014602052604081205593505b816001600160a01b03167fa82ad8dba07d5fde98bd3f0ef9b20c6426de9d477bb7647d46e0c7e50c7dc1b282604051610b0991815260200190565b60405180910390a25050600101610a58565b508015610b7d57603354610b39906001600160a01b03168583611199565b836001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e82604051610b7491815260200190565b60405180910390a25b9150505b9392505050565b8451610b9686868686611041565b5f5b81811015610c2e575f878281518110610bb357610bb3612a0b565b602002602001015190505f610bcb825f805f806111fc565b6001600160a01b0385165f9081526014602052604081208054908290559194509092509050610bfc8483858a6112c5565b90508015610c1f576001600160a01b0384165f9081526014602052604090208190555b50505050806001019050610b98565b50505050505050565b6040805160018082528183019092525f916020808301908036833701905050905081815f81518110610c6b57610c6b612a0b565b60200260200101906001600160a01b031690816001600160a01b031681525050610cf281600d805480602002602001604051908101604052809291908181526020018280548015610ce357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610cc5575b50505050506001806001610b88565b5050565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610d2a57610d2a612a0b565b60200260200101906001600160a01b031690816001600160a01b031681525050610d578183600180610f09565b505050565b60366020525f9081526040902080548190610d7690612a46565b80601f0160208091040260200160405190810160405280929190818152602001828054610da290612a46565b8015610ded5780601f10610dc457610100808354040283529160200191610ded565b820191905f5260205f20905b815481529060010190602001808311610dd057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b610e11611573565b5f610e1e83835f806112c5565b90508015610e5c5760405162461bcd60e51b81526020600482015260066024820152656e6f2078767360d01b60448201526064015b60405180910390fd5b826001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e83604051610e9791815260200190565b60405180910390a2505050565b610f0681600d805480602002602001604051908101604052809291908181526020018280548015610efc57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ede575b5050505050610cf6565b50565b610f16848484845f610b88565b50505050565b6008602052815f5260405f208181548110610f35575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610f7a57610f7a612a7e565b815260208101919091526040015f205460ff169392505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90610fc69033908590600401612a92565b602060405180830381865afa158015610fe1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110059190612ab5565b610f065760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e53565b835183515f9190825b8181101561118f575f87828151811061106557611065612a0b565b6020026020010151905061108061107b826115bf565b6115e1565b861561113d575f6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f29190612ad0565b905290506111008282611626565b5f95505b8486101561113b57611130828b888151811061112257611122612a0b565b6020026020010151836117bc565b856001019550611104565b505b85156111865761114c81611940565b5f94505b838510156111865761117b818a878151811061116e5761116e612a0b565b6020026020010151611aac565b846001019450611150565b5060010161104a565b5050505050505050565b6040516001600160a01b038316602482015260448101829052610d5790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c4a565b5f80808084600181111561121257611212612a7e565b036112205761122088611d1d565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e9061125e9030908f908f908f908f908f90600401612ae7565b606060405180830381865afa158015611279573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061129d9190612b42565b9250925092508260148111156112b5576112b5612a7e565b9b919a5098509650505050505050565b5f73ef044206db68e40520bfa82d45419d498b4bc7bf6001600160a01b038616148015906113105750737589dd3355dae848fdbf75044a3495351655cb1a6001600160a01b03861614155b801561133957507333df7a7f6d44307e1e5f3b15975b47515e5524c06001600160a01b03861614155b801561136257507324e77e5b74b30b026e9996e4bc3329c881e249686001600160a01b03861614155b61139c5760405162461bcd60e51b815260206004820152600b60248201526a109b1858dadb1a5cdd195960aa1b6044820152606401610e53565b6033546001600160a01b031684158061141957506040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113f2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114169190612ad0565b85115b15611427578491505061156b565b835f0361144b576114426001600160a01b0382168787611199565b5f91505061156b565b826114835760405162461bcd60e51b815260206004820152600860248201526718985b9adc9d5c1d60c21b6044820152606401610e53565b6034546001600160a01b039081169061149f908316825f611e34565b6114b36001600160a01b0383168288611e34565b5f6040516323323e0360e01b81526001600160a01b038981166004830152602482018990528316906323323e03906044016020604051808303815f875af1158015611500573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115249190612ad0565b146115655760405162461bcd60e51b815260206004820152601160248201527036b4b73a103132b430b6331032b93937b960791b6044820152606401610e53565b5f925050505b949350505050565b5f546001600160a01b031633146115bd5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e53565b565b5f60095f6115cd5f85610937565b81526020019081526020015f209050919050565b805460ff16610f065760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e53565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611652611f47565b83549091505f906116739063ffffffff80851691600160e01b900416611f80565b9050801580159061168357508215155b15611792575f6116f2876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116ec9190612ad0565b87611fb9565b90505f6116ff8386611fd6565b90505f825f0361171d5760405180602001604052805f815250611727565b6117278284612017565b604080516020810190915288546001600160e01b0316815290915061177090611750908361205a565b516040805180820190915260038152620c8c8d60ea1b6020820152612083565b6001600160e01b0316600160e01b63ffffffff871602178755506117b4915050565b80156117b45783546001600160e01b0316600160e01b63ffffffff8416021784555b505050505050565b601b546001600160a01b0316156117d5576117d56120b1565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b0390921690819055908015801561183157506a0c097ce7bc90715b34b9f160241b8210155b1561184757506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061185d8585611f80565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f916118b6916118b0918a16906395dd919390602401602060405180830381865afa1580156116c8573d5f803e3d5ffd5b83612240565b6001600160a01b0387165f908152601460205260409020549091506118db9082612267565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161196c611f47565b83549091505f9061198d9063ffffffff80851691600160e01b900416611f80565b9050801580159061199d57508215155b15611a83575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119df573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a039190612ad0565b90505f611a108386611fd6565b90505f825f03611a2e5760405180602001604052805f815250611a38565b611a388284612017565b604080516020810190915288546001600160e01b03168152909150611a6190611750908361205a565b6001600160e01b0316600160e01b63ffffffff87160217875550611aa5915050565b8015611aa55783546001600160e01b0316600160e01b63ffffffff8416021784555b5050505050565b601b546001600160a01b031615611ac557611ac56120b1565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b03909216908190559080158015611b2157506a0c097ce7bc90715b34b9f160241b8210155b15611b3757506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611b4d8585611f80565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f91611bc191908816906370a0823190602401602060405180830381865afa158015611b9d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b09190612ad0565b6001600160a01b0386165f90815260146020526040902054909150611be69082612267565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f611c9e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661229c9092919063ffffffff16565b905080515f1480611cbe575080806020019051810190611cbe9190612ab5565b610d575760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e53565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015611d9357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611d75575b505083519394505f925050505b81811015611aa557836001600160a01b031663a9c3cab1848381518110611dc957611dc9612a0b565b60200260200101516040518263ffffffff1660e01b8152600401611dfc91906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015611e13575f80fd5b505af1158015611e25573d5f803e3d5ffd5b50505050806001019050611da0565b801580611eac5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611e86573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eaa9190612ad0565b155b611f175760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e53565b6040516001600160a01b038316602482015260448101829052610d5790849063095ea7b360e01b906064016111c5565b5f611f7b4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b8152506122aa565b905090565b5f610b818383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b8152506122d1565b5f610b81611fcf84670de0b6b3a7640000611fd6565b83516122ff565b5f610b8183836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612331565b60408051602081019091525f8152604051806020016040528061205161204b866a0c097ce7bc90715b34b9f160241b611fd6565b856122ff565b90529392505050565b60408051602081019091525f81526040518060200160405280612051855f0151855f0151612267565b5f81600160e01b84106120a95760405162461bcd60e51b8152600401610e539190612b6d565b509192915050565b601c5415806120c15750601c5443105b156120c857565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015612112573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121369190612ad0565b9050805f03612143575050565b5f8061215143601c54611f80565b90505f612160601a5483611fd6565b905080841061217157809250612175565b8392505b601d54831015612186575050505050565b43601c55601b546121a4906001600160a01b03878116911685611199565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612223575f80fd5b505af1158015612235573d5f803e3d5ffd5b505050505050505050565b5f6a0c097ce7bc90715b34b9f160241b61225d84845f0151611fd6565b610b819190612b7f565b5f610b818383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b81525061238a565b606061156b84845f856123ba565b5f8164010000000084106120a95760405162461bcd60e51b8152600401610e539190612b6d565b5f81848411156122f45760405162461bcd60e51b8152600401610e539190612b6d565b5061156b8385612b9e565b5f610b8183836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612491565b5f83158061233d575082155b1561234957505f610b81565b5f6123548486612bb1565b9050836123618683612b7f565b1483906123815760405162461bcd60e51b8152600401610e539190612b6d565b50949350505050565b5f806123968486612a33565b905082858210156123815760405162461bcd60e51b8152600401610e539190612b6d565b60608247101561241b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e53565b5f80866001600160a01b031685876040516124369190612bc8565b5f6040518083038185875af1925050503d805f8114612470576040519150601f19603f3d011682016040523d82523d5f602084013e612475565b606091505b5091509150612486878383876124bc565b979650505050505050565b5f81836124b15760405162461bcd60e51b8152600401610e539190612b6d565b5061156b8385612b7f565b6060831561252a5782515f03612523576001600160a01b0385163b6125235760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e53565b508161156b565b61156b838381511561253f5781518083602001fd5b8060405162461bcd60e51b8152600401610e539190612b6d565b6001600160a01b0381168114610f06575f80fd5b5f6020828403121561257d575f80fd5b8135610b8181612559565b5f8060408385031215612599575f80fd5b82356125a481612559565b915060208301356125b481612559565b809150509250929050565b80356001600160601b03811681146125d5575f80fd5b919050565b5f80604083850312156125eb575f80fd5b6125a4836125bf565b5f60208284031215612604575f80fd5b5035919050565b5f805f6040848603121561261d575f80fd5b833567ffffffffffffffff80821115612634575f80fd5b818601915086601f830112612647575f80fd5b813581811115612655575f80fd5b8760208260051b8501011115612669575f80fd5b6020928301955093505084013561267f81612559565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156126c7576126c761268a565b604052919050565b5f67ffffffffffffffff8211156126e8576126e861268a565b5060051b60200190565b5f82601f830112612701575f80fd5b81356020612716612711836126cf565b61269e565b8083825260208201915060208460051b870101935086841115612737575f80fd5b602086015b8481101561275c57803561274f81612559565b835291830191830161273c565b509695505050505050565b5f82601f830112612776575f80fd5b81356020612786612711836126cf565b8083825260208201915060208460051b8701019350868411156127a7575f80fd5b602086015b8481101561275c5780356127bf81612559565b83529183019183016127ac565b8015158114610f06575f80fd5b5f805f805f60a086880312156127ed575f80fd5b853567ffffffffffffffff80821115612804575f80fd5b61281089838a016126f2565b96506020880135915080821115612825575f80fd5b5061283288828901612767565b9450506040860135612843816127cc565b92506060860135612853816127cc565b91506080860135612863816127cc565b809150509295509295909350565b5f8060408385031215612882575f80fd5b823561288d81612559565b9150602083013567ffffffffffffffff8111156128a8575f80fd5b6128b485828601612767565b9150509250929050565b5f602082840312156128ce575f80fd5b610b81826125bf565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61291760608301866128d7565b931515602083015250901515604090910152919050565b5f806040838503121561293f575f80fd5b823561294a81612559565b946020939093013593505050565b5f805f806080858703121561296b575f80fd5b843567ffffffffffffffff80821115612982575f80fd5b61298e888389016126f2565b955060208701359150808211156129a3575f80fd5b506129b087828801612767565b93505060408501356129c1816127cc565b915060608501356129d1816127cc565b939692955090935050565b5f80604083850312156129ed575f80fd5b82356129f881612559565b91506020830135600981106125b4575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561095257610952612a1f565b600181811c90821680612a5a57607f821691505b602082108103612a7857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040602082018190525f9061156b908301846128d7565b5f60208284031215612ac5575f80fd5b8151610b81816127cc565b5f60208284031215612ae0575f80fd5b5051919050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c0810160028310612b3157634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f60608486031215612b54575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610b8160208301846128d7565b5f82612b9957634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561095257610952612a1f565b808202811582820484141761095257610952612a1f565b5f82518060208501845e5f92019182525091905056fea264697066735822122044d010f5dd403212b52b7825526a1773704f146a219adf551df8cfd8b0b6a56c64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061037d575f3560e01c806394b2294b116101d4578063c7ee005e11610109578063e0f6123d116100a9578063ededbae611610079578063ededbae6146108de578063f445d703146108ef578063f851a4401461091c578063fa6331d81461092e575f80fd5b8063e0f6123d14610869578063e37d4b791461088b578063e85a2960146108c2578063e8755446146108d5575f80fd5b8063d463654c116100e4578063d463654c14610824578063d7c46d2d1461082b578063dce1544914610843578063dcfbc0c714610856575f80fd5b8063c7ee005e146107eb578063d09c54ba146107fe578063d3270f9914610811575f80fd5b8063b8324c7c11610174578063bec04f721161014f578063bec04f7214610791578063bf32442d1461079a578063c5b4db55146107ab578063c5f956af146107d8575f80fd5b8063b8324c7c14610704578063bb82aa5e1461075f578063bbb8864a14610772575f80fd5b8063a657e579116101af578063a657e579146106b8578063a7604b41146106cb578063adcd5fb9146106de578063b2eafc39146106f1575f80fd5b806394b2294b1461067a57806396c99064146106835780639bb27d62146106a5575f80fd5b806352d84d1e116102b55780637858524d1161025557806386df31ee1161022557806386df31ee146106135780638a7dc165146106265780638c1ac18a146106455780639254f5e514610667575f80fd5b80637858524d146105cd5780637d172bd5146105e05780637dc0d1d0146105f35780637fb8e8cd14610606575f80fd5b806370bf66f01161029057806370bf66f01461055d578063719f701b14610572578063737690991461057b57806376551383146105bb575f80fd5b806352d84d1e146105185780635dd3fc9d1461052b578063655f07251461054a575f80fd5b8063267822471161032057806341a18d2c116102fb57806341a18d2c146104a9578063425fad58146104d35780634a584432146104e65780634d99c77614610505575f80fd5b8063267822471461046a5780632bc7e29e1461047d5780634088c73e1461049c575f80fd5b80630db4b4e51161035b5780630db4b4e5146103e657806310b98338146103ef57806321af45691461042c57806324a3d62214610457575f80fd5b806302c3bcbb1461038157806304ef9d58146103b357806308e0225c146103bc575b5f80fd5b6103a061038f36600461256d565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103a060225481565b6103a06103ca366004612588565b601360209081525f928352604080842090915290825290205481565b6103a0601d5481565b61041c6103fd366004612588565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103aa565b601e5461043f906001600160a01b031681565b6040516001600160a01b0390911681526020016103aa565b600a5461043f906001600160a01b031681565b60015461043f906001600160a01b031681565b6103a061048b36600461256d565b60166020525f908152604090205481565b60185461041c9060ff1681565b6103a06104b7366004612588565b601260209081525f928352604080842090915290825290205481565b60185461041c9062010000900460ff1681565b6103a06104f436600461256d565b601f6020525f908152604090205481565b6103a06105133660046125da565b610937565b61043f6105263660046125f4565b610958565b6103a061053936600461256d565b602b6020525f908152604090205481565b6103a061055836600461260b565b610980565b61057061056b3660046127d9565b610b88565b005b6103a0601c5481565b6105a361058936600461256d565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103aa565b60185461041c90610100900460ff1681565b6105706105db36600461256d565b610c37565b601b5461043f906001600160a01b031681565b60045461043f906001600160a01b031681565b60395461041c9060ff1681565b610570610621366004612871565b610cf6565b6103a061063436600461256d565b60146020525f908152604090205481565b61041c61065336600461256d565b602d6020525f908152604090205460ff1681565b60155461043f906001600160a01b031681565b6103a060075481565b6106966106913660046128be565b610d5c565b6040516103aa93929190612905565b60255461043f906001600160a01b031681565b6037546105a3906001600160601b031681565b6105706106d936600461292e565b610e09565b6105706106ec36600461256d565b610ea4565b60205461043f906001600160a01b031681565b61073b61071236600461256d565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103aa565b60025461043f906001600160a01b031681565b6103a061078036600461256d565b602a6020525f908152604090205481565b6103a060175481565b6033546001600160a01b031661043f565b6107c06a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020016103aa565b60215461043f906001600160a01b031681565b60315461043f906001600160a01b031681565b61057061080c366004612958565b610f09565b60265461043f906001600160a01b031681565b6105a35f81565b60395461043f9061010090046001600160a01b031681565b61043f61085136600461292e565b610f1c565b60035461043f906001600160a01b031681565b61041c61087736600461256d565b60386020525f908152604090205460ff1681565b61073b61089936600461256d565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61041c6108d03660046129dc565b610f50565b6103a060055481565b6034546001600160a01b031661043f565b61041c6108fd366004612588565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461043f906001600160a01b031681565b6103a0601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d8181548110610967575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f6109bf6040518060400160405280601d81526020017f7365697a6556656e757328616464726573735b5d2c6164647265737329000000815250610f94565b604080516020808602828101820190935285825285925f92610a569290918991869182918501908490808284375f9201919091525050600d805460408051602080840282018101909252828152945091925090830182828015610a4957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a2b575b5050505050600180611041565b5f5b82811015610b1b575f878783818110610a7357610a73612a0b565b9050602002016020810190610a88919061256d565b6001600160a01b0381165f908152601460205260409020549091508015610ace57610ab38185612a33565b6001600160a01b0383165f9081526014602052604081205593505b816001600160a01b03167fa82ad8dba07d5fde98bd3f0ef9b20c6426de9d477bb7647d46e0c7e50c7dc1b282604051610b0991815260200190565b60405180910390a25050600101610a58565b508015610b7d57603354610b39906001600160a01b03168583611199565b836001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e82604051610b7491815260200190565b60405180910390a25b9150505b9392505050565b8451610b9686868686611041565b5f5b81811015610c2e575f878281518110610bb357610bb3612a0b565b602002602001015190505f610bcb825f805f806111fc565b6001600160a01b0385165f9081526014602052604081208054908290559194509092509050610bfc8483858a6112c5565b90508015610c1f576001600160a01b0384165f9081526014602052604090208190555b50505050806001019050610b98565b50505050505050565b6040805160018082528183019092525f916020808301908036833701905050905081815f81518110610c6b57610c6b612a0b565b60200260200101906001600160a01b031690816001600160a01b031681525050610cf281600d805480602002602001604051908101604052809291908181526020018280548015610ce357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610cc5575b50505050506001806001610b88565b5050565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610d2a57610d2a612a0b565b60200260200101906001600160a01b031690816001600160a01b031681525050610d578183600180610f09565b505050565b60366020525f9081526040902080548190610d7690612a46565b80601f0160208091040260200160405190810160405280929190818152602001828054610da290612a46565b8015610ded5780601f10610dc457610100808354040283529160200191610ded565b820191905f5260205f20905b815481529060010190602001808311610dd057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b610e11611573565b5f610e1e83835f806112c5565b90508015610e5c5760405162461bcd60e51b81526020600482015260066024820152656e6f2078767360d01b60448201526064015b60405180910390fd5b826001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e83604051610e9791815260200190565b60405180910390a2505050565b610f0681600d805480602002602001604051908101604052809291908181526020018280548015610efc57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ede575b5050505050610cf6565b50565b610f16848484845f610b88565b50505050565b6008602052815f5260405f208181548110610f35575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610f7a57610f7a612a7e565b815260208101919091526040015f205460ff169392505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90610fc69033908590600401612a92565b602060405180830381865afa158015610fe1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110059190612ab5565b610f065760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e53565b835183515f9190825b8181101561118f575f87828151811061106557611065612a0b565b6020026020010151905061108061107b826115bf565b6115e1565b861561113d575f6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f29190612ad0565b905290506111008282611626565b5f95505b8486101561113b57611130828b888151811061112257611122612a0b565b6020026020010151836117bc565b856001019550611104565b505b85156111865761114c81611940565b5f94505b838510156111865761117b818a878151811061116e5761116e612a0b565b6020026020010151611aac565b846001019450611150565b5060010161104a565b5050505050505050565b6040516001600160a01b038316602482015260448101829052610d5790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c4a565b5f80808084600181111561121257611212612a7e565b036112205761122088611d1d565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e9061125e9030908f908f908f908f908f90600401612ae7565b606060405180830381865afa158015611279573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061129d9190612b42565b9250925092508260148111156112b5576112b5612a7e565b9b919a5098509650505050505050565b5f73ef044206db68e40520bfa82d45419d498b4bc7bf6001600160a01b038616148015906113105750737589dd3355dae848fdbf75044a3495351655cb1a6001600160a01b03861614155b801561133957507333df7a7f6d44307e1e5f3b15975b47515e5524c06001600160a01b03861614155b801561136257507324e77e5b74b30b026e9996e4bc3329c881e249686001600160a01b03861614155b61139c5760405162461bcd60e51b815260206004820152600b60248201526a109b1858dadb1a5cdd195960aa1b6044820152606401610e53565b6033546001600160a01b031684158061141957506040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113f2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114169190612ad0565b85115b15611427578491505061156b565b835f0361144b576114426001600160a01b0382168787611199565b5f91505061156b565b826114835760405162461bcd60e51b815260206004820152600860248201526718985b9adc9d5c1d60c21b6044820152606401610e53565b6034546001600160a01b039081169061149f908316825f611e34565b6114b36001600160a01b0383168288611e34565b5f6040516323323e0360e01b81526001600160a01b038981166004830152602482018990528316906323323e03906044016020604051808303815f875af1158015611500573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115249190612ad0565b146115655760405162461bcd60e51b815260206004820152601160248201527036b4b73a103132b430b6331032b93937b960791b6044820152606401610e53565b5f925050505b949350505050565b5f546001600160a01b031633146115bd5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e53565b565b5f60095f6115cd5f85610937565b81526020019081526020015f209050919050565b805460ff16610f065760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e53565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611652611f47565b83549091505f906116739063ffffffff80851691600160e01b900416611f80565b9050801580159061168357508215155b15611792575f6116f2876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116ec9190612ad0565b87611fb9565b90505f6116ff8386611fd6565b90505f825f0361171d5760405180602001604052805f815250611727565b6117278284612017565b604080516020810190915288546001600160e01b0316815290915061177090611750908361205a565b516040805180820190915260038152620c8c8d60ea1b6020820152612083565b6001600160e01b0316600160e01b63ffffffff871602178755506117b4915050565b80156117b45783546001600160e01b0316600160e01b63ffffffff8416021784555b505050505050565b601b546001600160a01b0316156117d5576117d56120b1565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b0390921690819055908015801561183157506a0c097ce7bc90715b34b9f160241b8210155b1561184757506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061185d8585611f80565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f916118b6916118b0918a16906395dd919390602401602060405180830381865afa1580156116c8573d5f803e3d5ffd5b83612240565b6001600160a01b0387165f908152601460205260409020549091506118db9082612267565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161196c611f47565b83549091505f9061198d9063ffffffff80851691600160e01b900416611f80565b9050801580159061199d57508215155b15611a83575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119df573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a039190612ad0565b90505f611a108386611fd6565b90505f825f03611a2e5760405180602001604052805f815250611a38565b611a388284612017565b604080516020810190915288546001600160e01b03168152909150611a6190611750908361205a565b6001600160e01b0316600160e01b63ffffffff87160217875550611aa5915050565b8015611aa55783546001600160e01b0316600160e01b63ffffffff8416021784555b5050505050565b601b546001600160a01b031615611ac557611ac56120b1565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b03909216908190559080158015611b2157506a0c097ce7bc90715b34b9f160241b8210155b15611b3757506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611b4d8585611f80565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f91611bc191908816906370a0823190602401602060405180830381865afa158015611b9d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b09190612ad0565b6001600160a01b0386165f90815260146020526040902054909150611be69082612267565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f611c9e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661229c9092919063ffffffff16565b905080515f1480611cbe575080806020019051810190611cbe9190612ab5565b610d575760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e53565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015611d9357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611d75575b505083519394505f925050505b81811015611aa557836001600160a01b031663a9c3cab1848381518110611dc957611dc9612a0b565b60200260200101516040518263ffffffff1660e01b8152600401611dfc91906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015611e13575f80fd5b505af1158015611e25573d5f803e3d5ffd5b50505050806001019050611da0565b801580611eac5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611e86573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eaa9190612ad0565b155b611f175760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e53565b6040516001600160a01b038316602482015260448101829052610d5790849063095ea7b360e01b906064016111c5565b5f611f7b4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b8152506122aa565b905090565b5f610b818383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b8152506122d1565b5f610b81611fcf84670de0b6b3a7640000611fd6565b83516122ff565b5f610b8183836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612331565b60408051602081019091525f8152604051806020016040528061205161204b866a0c097ce7bc90715b34b9f160241b611fd6565b856122ff565b90529392505050565b60408051602081019091525f81526040518060200160405280612051855f0151855f0151612267565b5f81600160e01b84106120a95760405162461bcd60e51b8152600401610e539190612b6d565b509192915050565b601c5415806120c15750601c5443105b156120c857565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015612112573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121369190612ad0565b9050805f03612143575050565b5f8061215143601c54611f80565b90505f612160601a5483611fd6565b905080841061217157809250612175565b8392505b601d54831015612186575050505050565b43601c55601b546121a4906001600160a01b03878116911685611199565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612223575f80fd5b505af1158015612235573d5f803e3d5ffd5b505050505050505050565b5f6a0c097ce7bc90715b34b9f160241b61225d84845f0151611fd6565b610b819190612b7f565b5f610b818383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b81525061238a565b606061156b84845f856123ba565b5f8164010000000084106120a95760405162461bcd60e51b8152600401610e539190612b6d565b5f81848411156122f45760405162461bcd60e51b8152600401610e539190612b6d565b5061156b8385612b9e565b5f610b8183836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612491565b5f83158061233d575082155b1561234957505f610b81565b5f6123548486612bb1565b9050836123618683612b7f565b1483906123815760405162461bcd60e51b8152600401610e539190612b6d565b50949350505050565b5f806123968486612a33565b905082858210156123815760405162461bcd60e51b8152600401610e539190612b6d565b60608247101561241b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e53565b5f80866001600160a01b031685876040516124369190612bc8565b5f6040518083038185875af1925050503d805f8114612470576040519150601f19603f3d011682016040523d82523d5f602084013e612475565b606091505b5091509150612486878383876124bc565b979650505050505050565b5f81836124b15760405162461bcd60e51b8152600401610e539190612b6d565b5061156b8385612b7f565b6060831561252a5782515f03612523576001600160a01b0385163b6125235760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e53565b508161156b565b61156b838381511561253f5781518083602001fd5b8060405162461bcd60e51b8152600401610e539190612b6d565b6001600160a01b0381168114610f06575f80fd5b5f6020828403121561257d575f80fd5b8135610b8181612559565b5f8060408385031215612599575f80fd5b82356125a481612559565b915060208301356125b481612559565b809150509250929050565b80356001600160601b03811681146125d5575f80fd5b919050565b5f80604083850312156125eb575f80fd5b6125a4836125bf565b5f60208284031215612604575f80fd5b5035919050565b5f805f6040848603121561261d575f80fd5b833567ffffffffffffffff80821115612634575f80fd5b818601915086601f830112612647575f80fd5b813581811115612655575f80fd5b8760208260051b8501011115612669575f80fd5b6020928301955093505084013561267f81612559565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156126c7576126c761268a565b604052919050565b5f67ffffffffffffffff8211156126e8576126e861268a565b5060051b60200190565b5f82601f830112612701575f80fd5b81356020612716612711836126cf565b61269e565b8083825260208201915060208460051b870101935086841115612737575f80fd5b602086015b8481101561275c57803561274f81612559565b835291830191830161273c565b509695505050505050565b5f82601f830112612776575f80fd5b81356020612786612711836126cf565b8083825260208201915060208460051b8701019350868411156127a7575f80fd5b602086015b8481101561275c5780356127bf81612559565b83529183019183016127ac565b8015158114610f06575f80fd5b5f805f805f60a086880312156127ed575f80fd5b853567ffffffffffffffff80821115612804575f80fd5b61281089838a016126f2565b96506020880135915080821115612825575f80fd5b5061283288828901612767565b9450506040860135612843816127cc565b92506060860135612853816127cc565b91506080860135612863816127cc565b809150509295509295909350565b5f8060408385031215612882575f80fd5b823561288d81612559565b9150602083013567ffffffffffffffff8111156128a8575f80fd5b6128b485828601612767565b9150509250929050565b5f602082840312156128ce575f80fd5b610b81826125bf565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61291760608301866128d7565b931515602083015250901515604090910152919050565b5f806040838503121561293f575f80fd5b823561294a81612559565b946020939093013593505050565b5f805f806080858703121561296b575f80fd5b843567ffffffffffffffff80821115612982575f80fd5b61298e888389016126f2565b955060208701359150808211156129a3575f80fd5b506129b087828801612767565b93505060408501356129c1816127cc565b915060608501356129d1816127cc565b939692955090935050565b5f80604083850312156129ed575f80fd5b82356129f881612559565b91506020830135600981106125b4575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561095257610952612a1f565b600181811c90821680612a5a57607f821691505b602082108103612a7857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040602082018190525f9061156b908301846128d7565b5f60208284031215612ac5575f80fd5b8151610b81816127cc565b5f60208284031215612ae0575f80fd5b5051919050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c0810160028310612b3157634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f60608486031215612b54575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610b8160208301846128d7565b5f82612b9957634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561095257610952612a1f565b808202811582820484141761095257610952612a1f565b5f82518060208501845e5f92019182525091905056fea264697066735822122044d010f5dd403212b52b7825526a1773704f146a219adf551df8cfd8b0b6a56c64736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This facet contains all the methods related to the reward functionality", @@ -1411,6 +1424,7 @@ } }, "claimVenus(address[],address[],bool,bool,bool)": { + "details": "The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices. When DBO protection mode is active, a holder with a position that is healthy at spot prices may still show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO.", "params": { "borrowers": "Whether or not to claim XVS earned by borrowing", "collateral": "Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall", @@ -1621,6 +1635,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "flashLoanPaused()": { "notice": "Whether flash loans are paused system-wide" }, @@ -1730,7 +1747,7 @@ "storageLayout": { "storage": [ { - "astId": 1652, + "astId": 9226, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "admin", "offset": 0, @@ -1738,7 +1755,7 @@ "type": "t_address" }, { - "astId": 1655, + "astId": 9229, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "pendingAdmin", "offset": 0, @@ -1746,7 +1763,7 @@ "type": "t_address" }, { - "astId": 1658, + "astId": 9232, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "comptrollerImplementation", "offset": 0, @@ -1754,7 +1771,7 @@ "type": "t_address" }, { - "astId": 1661, + "astId": 9235, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -1762,15 +1779,15 @@ "type": "t_address" }, { - "astId": 1668, + "astId": 9242, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)967" + "type": "t_contract(ResilientOracleInterface)7913" }, { - "astId": 1671, + "astId": 9245, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "closeFactorMantissa", "offset": 0, @@ -1778,7 +1795,7 @@ "type": "t_uint256" }, { - "astId": 1674, + "astId": 9248, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -1786,7 +1803,7 @@ "type": "t_uint256" }, { - "astId": 1677, + "astId": 9251, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "maxAssets", "offset": 0, @@ -1794,23 +1811,23 @@ "type": "t_uint256" }, { - "astId": 1684, + "astId": 9258, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)17915)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)" }, { - "astId": 1718, + "astId": 9292, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11388,t_struct(Market)1711_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)" }, { - "astId": 1721, + "astId": 9295, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "pauseGuardian", "offset": 0, @@ -1818,7 +1835,7 @@ "type": "t_address" }, { - "astId": 1724, + "astId": 9298, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -1826,7 +1843,7 @@ "type": "t_bool" }, { - "astId": 1727, + "astId": 9301, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -1834,7 +1851,7 @@ "type": "t_bool" }, { - "astId": 1730, + "astId": 9304, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "transferGuardianPaused", "offset": 22, @@ -1842,7 +1859,7 @@ "type": "t_bool" }, { - "astId": 1733, + "astId": 9307, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -1850,7 +1867,7 @@ "type": "t_bool" }, { - "astId": 1738, + "astId": 9312, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "mintGuardianPaused", "offset": 0, @@ -1858,7 +1875,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1743, + "astId": 9317, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -1866,15 +1883,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1755, + "astId": 9329, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)17915)dyn_storage" + "type": "t_array(t_contract(VToken)49461)dyn_storage" }, { - "astId": 1758, + "astId": 9332, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusRate", "offset": 0, @@ -1882,7 +1899,7 @@ "type": "t_uint256" }, { - "astId": 1763, + "astId": 9337, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusSpeeds", "offset": 0, @@ -1890,23 +1907,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1769, + "astId": 9343, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1775, + "astId": 9349, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1782, + "astId": 9356, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusSupplierIndex", "offset": 0, @@ -1914,7 +1931,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1789, + "astId": 9363, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -1922,7 +1939,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1794, + "astId": 9368, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusAccrued", "offset": 0, @@ -1930,15 +1947,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1798, + "astId": 9372, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)11813" + "type": "t_contract(VAIControllerInterface)42511" }, { - "astId": 1803, + "astId": 9377, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "mintedVAIs", "offset": 0, @@ -1946,7 +1963,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1806, + "astId": 9380, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "vaiMintRate", "offset": 0, @@ -1954,7 +1971,7 @@ "type": "t_uint256" }, { - "astId": 1809, + "astId": 9383, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -1962,7 +1979,7 @@ "type": "t_bool" }, { - "astId": 1811, + "astId": 9385, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -1970,7 +1987,7 @@ "type": "t_bool" }, { - "astId": 1814, + "astId": 9388, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "protocolPaused", "offset": 2, @@ -1978,7 +1995,7 @@ "type": "t_bool" }, { - "astId": 1817, + "astId": 9391, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusVAIRate", "offset": 0, @@ -1986,7 +2003,7 @@ "type": "t_uint256" }, { - "astId": 1823, + "astId": 9397, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -1994,7 +2011,7 @@ "type": "t_uint256" }, { - "astId": 1825, + "astId": 9399, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "vaiVaultAddress", "offset": 0, @@ -2002,7 +2019,7 @@ "type": "t_address" }, { - "astId": 1827, + "astId": 9401, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "releaseStartBlock", "offset": 0, @@ -2010,7 +2027,7 @@ "type": "t_uint256" }, { - "astId": 1829, + "astId": 9403, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "minReleaseAmount", "offset": 0, @@ -2018,7 +2035,7 @@ "type": "t_uint256" }, { - "astId": 1835, + "astId": 9409, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "borrowCapGuardian", "offset": 0, @@ -2026,7 +2043,7 @@ "type": "t_address" }, { - "astId": 1840, + "astId": 9414, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "borrowCaps", "offset": 0, @@ -2034,7 +2051,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1846, + "astId": 9420, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "treasuryGuardian", "offset": 0, @@ -2042,7 +2059,7 @@ "type": "t_address" }, { - "astId": 1849, + "astId": 9423, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "treasuryAddress", "offset": 0, @@ -2050,7 +2067,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9426, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "treasuryPercent", "offset": 0, @@ -2058,7 +2075,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9434, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -2066,7 +2083,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1865, + "astId": 9439, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "lastContributorBlock", "offset": 0, @@ -2074,7 +2091,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1870, + "astId": 9444, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "liquidatorContract", "offset": 0, @@ -2082,15 +2099,15 @@ "type": "t_address" }, { - "astId": 1876, + "astId": 9450, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1635" + "type": "t_contract(ComptrollerLensInterface)9207" }, { - "astId": 1884, + "astId": 9458, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "supplyCaps", "offset": 0, @@ -2098,7 +2115,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9464, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "accessControl", "offset": 0, @@ -2106,7 +2123,7 @@ "type": "t_address" }, { - "astId": 1897, + "astId": 9471, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_actionPaused", "offset": 0, @@ -2114,7 +2131,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1905, + "astId": 9479, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -2122,7 +2139,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1910, + "astId": 9484, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -2130,7 +2147,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1920, + "astId": 9494, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "approvedDelegates", "offset": 0, @@ -2138,7 +2155,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1928, + "astId": 9502, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -2146,23 +2163,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1947, + "astId": 9521, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1936_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)" }, { - "astId": 1952, + "astId": 9526, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1942_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)" }, { - "astId": 1955, + "astId": 9529, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_facetAddresses", "offset": 0, @@ -2170,15 +2187,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1962, + "astId": 9536, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)11746" + "type": "t_contract(IPrime)33730" }, { - "astId": 1972, + "astId": 9546, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -2186,7 +2203,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1978, + "astId": 9552, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "xvs", "offset": 0, @@ -2194,7 +2211,7 @@ "type": "t_address" }, { - "astId": 1981, + "astId": 9555, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "xvsVToken", "offset": 0, @@ -2202,7 +2219,7 @@ "type": "t_address" }, { - "astId": 2003, + "astId": 9577, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "userPoolId", "offset": 0, @@ -2210,15 +2227,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2009, + "astId": 9583, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)1998_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)9572_storage)" }, { - "astId": 2012, + "astId": 9586, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "lastPoolId", "offset": 0, @@ -2226,7 +2243,7 @@ "type": "t_uint96" }, { - "astId": 2020, + "astId": 9594, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -2234,12 +2251,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2023, + "astId": 9597, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 9604, + "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)7883" } ], "types": { @@ -2260,8 +2285,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)17915)dyn_storage": { - "base": "t_contract(VToken)17915", + "t_array(t_contract(VToken)49461)dyn_storage": { + "base": "t_contract(VToken)49461", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -2276,37 +2301,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1635": { + "t_contract(ComptrollerLensInterface)9207": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)11746": { + "t_contract(IDeviationBoundedOracle)7883": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)33730": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)967": { + "t_contract(ResilientOracleInterface)7913": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)11813": { + "t_contract(VAIControllerInterface)42511": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)17915": { + "t_contract(VToken)49461": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)17915)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)17915)dyn_storage" + "value": "t_array(t_contract(VToken)49461)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -2336,19 +2366,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1942_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1942_storage" + "value": "t_struct(FacetFunctionSelectors)9516_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1750_storage" + "value": "t_struct(VenusMarketState)9324_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2364,12 +2394,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1936_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1936_storage" + "value": "t_struct(FacetAddressAndPosition)9510_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -2378,31 +2408,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)1998_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)9572_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)1998_storage" + "value": "t_struct(PoolData)9572_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11388,t_struct(Market)1711_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11388", + "key": "t_userDefinedValueType(PoolMarketId)19217", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1711_storage" + "value": "t_struct(Market)9285_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1936_storage": { + "t_struct(FacetAddressAndPosition)9510_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1933, + "astId": 9507, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "facetAddress", "offset": 0, @@ -2410,7 +2440,7 @@ "type": "t_address" }, { - "astId": 1935, + "astId": 9509, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "functionSelectorPosition", "offset": 20, @@ -2420,12 +2450,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1942_storage": { + "t_struct(FacetFunctionSelectors)9516_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1939, + "astId": 9513, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "functionSelectors", "offset": 0, @@ -2433,7 +2463,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1941, + "astId": 9515, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "facetAddressPosition", "offset": 0, @@ -2443,12 +2473,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1711_storage": { + "t_struct(Market)9285_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1687, + "astId": 9261, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isListed", "offset": 0, @@ -2456,7 +2486,7 @@ "type": "t_bool" }, { - "astId": 1690, + "astId": 9264, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -2464,7 +2494,7 @@ "type": "t_uint256" }, { - "astId": 1695, + "astId": 9269, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "accountMembership", "offset": 0, @@ -2472,7 +2502,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1698, + "astId": 9272, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isVenus", "offset": 0, @@ -2480,7 +2510,7 @@ "type": "t_bool" }, { - "astId": 1701, + "astId": 9275, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -2488,7 +2518,7 @@ "type": "t_uint256" }, { - "astId": 1704, + "astId": 9278, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -2496,7 +2526,7 @@ "type": "t_uint256" }, { - "astId": 1707, + "astId": 9281, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "poolId", "offset": 0, @@ -2504,7 +2534,7 @@ "type": "t_uint96" }, { - "astId": 1710, + "astId": 9284, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isBorrowAllowed", "offset": 12, @@ -2514,12 +2544,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)1998_storage": { + "t_struct(PoolData)9572_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 1987, + "astId": 9561, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "label", "offset": 0, @@ -2527,7 +2557,7 @@ "type": "t_string_storage" }, { - "astId": 1991, + "astId": 9565, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "vTokens", "offset": 0, @@ -2535,7 +2565,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1994, + "astId": 9568, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isActive", "offset": 0, @@ -2543,7 +2573,7 @@ "type": "t_bool" }, { - "astId": 1997, + "astId": 9571, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -2553,12 +2583,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1750_storage": { + "t_struct(VenusMarketState)9324_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1746, + "astId": 9320, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "index", "offset": 0, @@ -2566,7 +2596,7 @@ "type": "t_uint224" }, { - "astId": 1749, + "astId": 9323, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "block", "offset": 28, @@ -2596,7 +2626,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11388": { + "t_userDefinedValueType(PoolMarketId)19217": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bscmainnet/SetterFacet.json b/deployments/bscmainnet/SetterFacet.json index f58536690..1f197b6a1 100644 --- a/deployments/bscmainnet/SetterFacet.json +++ b/deployments/bscmainnet/SetterFacet.json @@ -1,5 +1,5 @@ { - "address": "0x11B38582c61058eDd9a526561567B4c7b02060e7", + "address": "0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0", "abi": [ { "inputs": [], @@ -531,6 +531,25 @@ "name": "NewComptrollerLens", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "oldDeviationBoundedOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "NewDeviationBoundedOracle", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1522,6 +1541,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -1955,6 +1987,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "setDeviationBoundedOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2510,28 +2561,28 @@ "type": "function" } ], - "transactionHash": "0x28ae7868e2317e0583c2aa4a09aef1a529f3856ee1821772957f22c818699110", + "transactionHash": "0x2220d9e4db32f34218e73fbeecee9baab89bcc60b296fa2b487824b07466c9d3", "receipt": { "to": null, - "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0x11B38582c61058eDd9a526561567B4c7b02060e7", - "transactionIndex": 154, - "gasUsed": "3396204", + "from": "0x9b0A3EAE7f174937d31745B710BbeA68e9D1BEf7", + "contractAddress": "0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0", + "transactionIndex": 61, + "gasUsed": "3458885", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xdb40fabade992017ea1a90f2bf104fa5585e954096bb0569df6b9745ef0f8d8a", - "transactionHash": "0x28ae7868e2317e0583c2aa4a09aef1a529f3856ee1821772957f22c818699110", + "blockHash": "0x32c23e8b546fe6b5e497bf7fdbf25699d24440d21ad97a3cb67f1c67634a5d87", + "transactionHash": "0x2220d9e4db32f34218e73fbeecee9baab89bcc60b296fa2b487824b07466c9d3", "logs": [], - "blockNumber": 66295043, - "cumulativeGasUsed": "27761380", + "blockNumber": 95559337, + "cumulativeGasUsed": "11351659", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 4, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPausedMarket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"ActionProtocolPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"BorrowAllowedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldPaused\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newPaused\",\"type\":\"bool\"}],\"name\":\"FlashLoanPauseChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"isWhitelisted\",\"type\":\"bool\"}],\"name\":\"IsAccountFlashLoanWhitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledForUserUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"NewAccessControl\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldComptrollerLens\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newComptrollerLens\",\"type\":\"address\"}],\"name\":\"NewComptrollerLens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationThresholdMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationThreshold\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldLiquidatorContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newLiquidatorContract\",\"type\":\"address\"}],\"name\":\"NewLiquidatorContract\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IPrime\",\"name\":\"oldPrimeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IPrime\",\"name\":\"newPrimeToken\",\"type\":\"address\"}],\"name\":\"NewPrimeToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSupplyCap\",\"type\":\"uint256\"}],\"name\":\"NewSupplyCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"}],\"name\":\"NewTreasuryAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"}],\"name\":\"NewTreasuryGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldTreasuryPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"NewTreasuryPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract VAIControllerInterface\",\"name\":\"oldVAIController\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract VAIControllerInterface\",\"name\":\"newVAIController\",\"type\":\"address\"}],\"name\":\"NewVAIController\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldVAIMintRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVAIMintRate\",\"type\":\"uint256\"}],\"name\":\"NewVAIMintRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vault_\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartBlock_\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseInterval_\",\"type\":\"uint256\"}],\"name\":\"NewVAIVaultInfo\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldVenusVAIVaultRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVenusVAIVaultRate\",\"type\":\"uint256\"}],\"name\":\"NewVenusVAIVaultRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldXVS\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newXVS\",\"type\":\"address\"}],\"name\":\"NewXVSToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldXVSVToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newXVSVToken\",\"type\":\"address\"}],\"name\":\"NewXVSVToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"PoolActiveStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"PoolFallbackStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"oldLabel\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newLabel\",\"type\":\"string\"}],\"name\":\"PoolLabelUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"_setAccessControl\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets_\",\"type\":\"address[]\"},{\"internalType\":\"enum Action[]\",\"name\":\"actions_\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}],\"name\":\"_setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"comptrollerLens_\",\"type\":\"address\"}],\"name\":\"_setComptrollerLens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"_setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"_setForcedLiquidationForUser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newLiquidatorContract_\",\"type\":\"address\"}],\"name\":\"_setLiquidatorContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_prime\",\"type\":\"address\"}],\"name\":\"_setPrimeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setProtocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"_setTreasuryData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"vaiController_\",\"type\":\"address\"}],\"name\":\"_setVAIController\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newVAIMintRate\",\"type\":\"uint256\"}],\"name\":\"_setVAIMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vault_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"releaseStartBlock_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minReleaseAmount_\",\"type\":\"uint256\"}],\"name\":\"_setVAIVaultInfo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"venusVAIVaultRate_\",\"type\":\"uint256\"}],\"name\":\"_setVenusVAIVaultRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"xvs_\",\"type\":\"address\"}],\"name\":\"_setXVSToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"xvsVToken_\",\"type\":\"address\"}],\"name\":\"_setXVSVToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets_\",\"type\":\"address[]\"},{\"internalType\":\"enum Action[]\",\"name\":\"actions_\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}],\"name\":\"setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"allowFallback\",\"type\":\"bool\"}],\"name\":\"setAllowCorePoolFallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"setFlashLoanPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"borrowAllowed\",\"type\":\"bool\"}],\"name\":\"setIsBorrowAllowed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setMintedVAIOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"}],\"name\":\"setPoolActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"string\",\"name\":\"newLabel\",\"type\":\"string\"}],\"name\":\"setPoolLabel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_prime\",\"type\":\"address\"}],\"name\":\"setPrimeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isWhiteListed\",\"type\":\"bool\"}],\"name\":\"setWhiteListFlashLoanAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the setters for the states\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setAccessControl(address)\":{\"details\":\"Allows the contract admin to set the address of access control of this contract\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"_setActionsPaused(address[],uint8[],bool)\":{\"details\":\"Allows a privileged role to pause/unpause the protocol action state\",\"params\":{\"actions_\":\"List of action ids to pause/unpause\",\"markets_\":\"Markets to pause/unpause the actions on\",\"paused_\":\"The new paused state (true=paused, false=unpaused)\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Allows the contract admin to set the closeFactor used to liquidate borrows\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"_setComptrollerLens(address)\":{\"details\":\"Set ComptrollerLens contract address\",\"params\":{\"comptrollerLens_\":\"The new ComptrollerLens contract address to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setForcedLiquidation(address,bool)\":{\"details\":\"Allows a privileged role to set enable/disable forced liquidations\",\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"_setForcedLiquidationForUser(address,address,bool)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"_setLiquidatorContract(address)\":{\"details\":\"Allows the contract admin to update the address of liquidator contract\",\"params\":{\"newLiquidatorContract_\":\"The new address of the liquidator contract\"}},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\",\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"_setMarketSupplyCaps(address[],uint256[])\":{\"details\":\"Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\",\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"_setPauseGuardian(address)\":{\"details\":\"Allows the contract admin to change the Pause Guardian\",\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"_setPriceOracle(address)\":{\"details\":\"Allows the contract admin to set a new price oracle used by the Comptroller\",\"params\":{\"newOracle\":\"The new price oracle to set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setPrimeToken(address)\":{\"params\":{\"_prime\":\"The new prime token contract to be set\"},\"returns\":{\"_0\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setProtocolPaused(bool)\":{\"details\":\"Allows a privileged role to pause/unpause protocol\",\"params\":{\"state\":\"The new state (true=paused, false=unpaused)\"},\"returns\":{\"_0\":\"bool The updated state of the protocol\"}},\"_setTreasuryData(address,address,uint256)\":{\"params\":{\"newTreasuryAddress\":\"The new address of the treasury to be set\",\"newTreasuryGuardian\":\"The new address of the treasury guardian to be set\",\"newTreasuryPercent\":\"The new treasury percent to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIController(address)\":{\"details\":\"Admin function to set a new VAI controller\",\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIMintRate(uint256)\":{\"params\":{\"newVAIMintRate\":\"The new VAI mint rate to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIVaultInfo(address,uint256,uint256)\":{\"params\":{\"minReleaseAmount_\":\"The minimum release amount to VAI Vault\",\"releaseStartBlock_\":\"The start block of release to VAI Vault\",\"vault_\":\"The address of the VAI Vault\"}},\"_setVenusVAIVaultRate(uint256)\":{\"params\":{\"venusVAIVaultRate_\":\"The amount of XVS wei per block to distribute to VAI Vault\"}},\"_setXVSToken(address)\":{\"params\":{\"xvs_\":\"The address of the XVS token\"}},\"_setXVSVToken(address)\":{\"params\":{\"xvsVToken_\":\"The address of the XVS vToken\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"setActionsPaused(address[],uint8[],bool)\":{\"params\":{\"actions_\":\"List of action ids to pause/unpause\",\"markets_\":\"Markets to pause/unpause the actions on\",\"paused_\":\"The new paused state (true=paused, false=unpaused)\"}},\"setAllowCorePoolFallback(uint96,bool)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.\",\"custom:event\":\"PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\",\"params\":{\"allowFallback\":\"True to allow fallback to Core Pool, false to disable.\",\"poolId\":\"ID of the pool to update.\"}},\"setCloseFactor(uint256)\":{\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"setCollateralFactor(address,uint256,uint256)\":{\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"vToken\":\"The market to set the factor on\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setCollateralFactor(uint96,address,uint256,uint256)\":{\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The market to set the factor on\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setFlashLoanPaused(bool)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits FlashLoanPauseChanged event\",\"params\":{\"paused\":\"True to pause flash loans, false to unpause\"}},\"setForcedLiquidation(address,bool)\":{\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"setIsBorrowAllowed(uint96,address,bool)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the pool ID is invalid.MarketConfigNotFound Reverts if the market is not listed in the pool.\",\"custom:event\":\"BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\",\"params\":{\"borrowAllowed\":\"The new borrow allowed status.\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The address of the market (vToken).\"}},\"setLiquidationIncentive(address,uint256)\":{\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\",\"vToken\":\"The market to set the liquidationIncentive for\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setLiquidationIncentive(uint96,address,uint256)\":{\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The market to set the liquidationIncentive for\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setMarketBorrowCaps(address[],uint256[])\":{\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"setMarketSupplyCaps(address[],uint256[])\":{\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"setMintedVAIOf(address,uint256)\":{\"params\":{\"amount\":\"The amount of VAI to set to the account\",\"owner\":\"The address of the account to set\"},\"returns\":{\"_0\":\"The number of minted VAI by `owner`\"}},\"setPoolActive(uint96,bool)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.\",\"custom:event\":\"PoolActiveStatusUpdated Emitted after the pool active status is updated.\",\"params\":{\"active\":\"true to enable, false to disable\",\"poolId\":\"id of the pool to update\"}},\"setPoolLabel(uint96,string)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core PoolPoolDoesNotExist Reverts if the target pool ID does not existEmptyPoolLabel Reverts if the provided label is an empty string\",\"custom:event\":\"PoolLabelUpdated Emitted after the pool label is updated\",\"params\":{\"newLabel\":\"The new label for the pool\",\"poolId\":\"ID of the pool to update\"}},\"setPriceOracle(address)\":{\"params\":{\"newOracle\":\"The new price oracle to set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"setPrimeToken(address)\":{\"params\":{\"_prime\":\"The new prime token contract to be set\"},\"returns\":{\"_0\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"setWhiteListFlashLoanAccount(address,bool)\":{\"custom:event\":\"Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\",\"params\":{\"account\":\"The account to authorize for flash loans\",\"isWhiteListed\":\"True to whitelist the account for flash loans, false to remove from whitelist\"}}},\"title\":\"SetterFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"ActionPausedMarket(address,uint8,bool)\":{\"notice\":\"Emitted when an action is paused on a market\"},\"ActionProtocolPaused(bool)\":{\"notice\":\"Emitted when protocol state is changed by admin\"},\"BorrowAllowedUpdated(uint96,address,bool,bool)\":{\"notice\":\"Emitted when the borrowAllowed flag is updated for a market\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"FlashLoanPauseChanged(bool,bool)\":{\"notice\":\"Emitted when flash loan pause status changes\"},\"IsAccountFlashLoanWhitelisted(address,bool)\":{\"notice\":\"Emitted when an account's flash loan whitelist status is updated\"},\"IsForcedLiquidationEnabledForUserUpdated(address,address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\"},\"IsForcedLiquidationEnabledUpdated(address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for all users in a market\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"NewAccessControl(address,address)\":{\"notice\":\"Emitted when access control address is changed by admin\"},\"NewBorrowCap(address,uint256)\":{\"notice\":\"Emitted when borrow cap for a vToken is changed\"},\"NewCloseFactor(uint256,uint256)\":{\"notice\":\"Emitted when close factor is changed by admin\"},\"NewCollateralFactor(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when a collateral factor for a market in a pool is changed by admin\"},\"NewComptrollerLens(address,address)\":{\"notice\":\"Emitted when ComptrollerLens address is changed\"},\"NewLiquidationIncentive(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation incentive for a market in a pool is changed by admin\"},\"NewLiquidationThreshold(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation threshold for a market in a pool is changed by admin\"},\"NewLiquidatorContract(address,address)\":{\"notice\":\"Emitted when liquidator adress is changed\"},\"NewPauseGuardian(address,address)\":{\"notice\":\"Emitted when pause guardian is changed\"},\"NewPriceOracle(address,address)\":{\"notice\":\"Emitted when price oracle is changed\"},\"NewPrimeToken(address,address)\":{\"notice\":\"Emitted when prime token contract address is changed\"},\"NewSupplyCap(address,uint256)\":{\"notice\":\"Emitted when supply cap for a vToken is changed\"},\"NewTreasuryAddress(address,address)\":{\"notice\":\"Emitted when treasury address is changed\"},\"NewTreasuryGuardian(address,address)\":{\"notice\":\"Emitted when treasury guardian is changed\"},\"NewTreasuryPercent(uint256,uint256)\":{\"notice\":\"Emitted when treasury percent is changed\"},\"NewVAIController(address,address)\":{\"notice\":\"Emitted when VAIController is changed\"},\"NewVAIMintRate(uint256,uint256)\":{\"notice\":\"Emitted when VAI mint rate is changed by admin\"},\"NewVAIVaultInfo(address,uint256,uint256)\":{\"notice\":\"Emitted when VAI Vault info is changed\"},\"NewVenusVAIVaultRate(uint256,uint256)\":{\"notice\":\"Emitted when Venus VAI Vault rate is changed\"},\"NewXVSToken(address,address)\":{\"notice\":\"Emitted when XVS token address is changed\"},\"NewXVSVToken(address,address)\":{\"notice\":\"Emitted when XVS vToken address is changed\"},\"PoolActiveStatusUpdated(uint96,bool,bool)\":{\"notice\":\"Emitted when pool active status updated\"},\"PoolFallbackStatusUpdated(uint96,bool,bool)\":{\"notice\":\"Emitted when pool Fallback status is updated\"},\"PoolLabelUpdated(uint96,string,string)\":{\"notice\":\"Emitted when pool label is updated\"}},\"kind\":\"user\",\"methods\":{\"_setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"_setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Pause/unpause certain actions\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setForcedLiquidation(address,bool)\":{\"notice\":\"Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity\"},\"_setForcedLiquidationForUser(address,address,bool)\":{\"notice\":\"Enables forced liquidations for user's borrows in a certain market. If forced liquidation is enabled, user's borrows in the market may be liquidated regardless of the account liquidity. Forced liquidation may be enabled for a user even if it is not enabled for the entire market.\"},\"_setLiquidatorContract(address)\":{\"notice\":\"Update the address of the liquidator contract\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\"},\"_setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_setPrimeToken(address)\":{\"notice\":\"Sets the prime token contract for the comptroller\"},\"_setProtocolPaused(bool)\":{\"notice\":\"Set whole protocol pause/unpause state\"},\"_setTreasuryData(address,address,uint256)\":{\"notice\":\"Set the treasury data.\"},\"_setVAIController(address)\":{\"notice\":\"Sets a new VAI controller\"},\"_setVAIMintRate(uint256)\":{\"notice\":\"Set the VAI mint rate\"},\"_setVAIVaultInfo(address,uint256,uint256)\":{\"notice\":\"Set the VAI Vault infos\"},\"_setVenusVAIVaultRate(uint256)\":{\"notice\":\"Set the amount of XVS distributed per block to VAI Vault\"},\"_setXVSToken(address)\":{\"notice\":\"Set the address of the XVS token\"},\"_setXVSVToken(address)\":{\"notice\":\"Set the address of the XVS vToken\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\"},\"setAllowCorePoolFallback(uint96,bool)\":{\"notice\":\"Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\"},\"setCloseFactor(uint256)\":{\"notice\":\"Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\"},\"setCollateralFactor(address,uint256,uint256)\":{\"notice\":\"Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\"},\"setCollateralFactor(uint96,address,uint256,uint256)\":{\"notice\":\"Sets the collateral factor and liquidation threshold for a market in the specified pool.\"},\"setFlashLoanPaused(bool)\":{\"notice\":\"Pause or unpause flash loans system-wide\"},\"setForcedLiquidation(address,bool)\":{\"notice\":\"Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\"},\"setIsBorrowAllowed(uint96,address,bool)\":{\"notice\":\"Updates the `isBorrowAllowed` flag for a market in a pool.\"},\"setLiquidationIncentive(address,uint256)\":{\"notice\":\"Sets the liquidation incentive for a market in the Core Pool only.\"},\"setLiquidationIncentive(uint96,address,uint256)\":{\"notice\":\"Sets the liquidation incentive for a market in the specified pool.\"},\"setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\"},\"setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\"},\"setMintedVAIOf(address,uint256)\":{\"notice\":\"Set the minted VAI amount of the `owner`\"},\"setPoolActive(uint96,bool)\":{\"notice\":\"updates active status for a specific pool (excluding the Core Pool)\"},\"setPoolLabel(uint96,string)\":{\"notice\":\"Updates the label for a specific pool (excluding the Core Pool)\"},\"setPriceOracle(address)\":{\"notice\":\"Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\"},\"setPrimeToken(address)\":{\"notice\":\"Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\"},\"setWhiteListFlashLoanAccount(address,bool)\":{\"notice\":\"Adds/Removes an account to the flash loan whitelist\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains all the configurational setter functions\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/SetterFacet.sol\":\"SetterFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/SetterFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../../ComptrollerLensInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../../../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { IPrime } from \\\"../../../Tokens/Prime/IPrime.sol\\\";\\nimport { ISetterFacet } from \\\"../interfaces/ISetterFacet.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\n/**\\n * @title SetterFacet\\n * @author Venus\\n * @dev This facet contains all the setters for the states\\n * @notice This facet contract contains all the configurational setter functions\\n */\\ncontract SetterFacet is ISetterFacet, FacetBase {\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor for a market in a pool is changed by admin\\n event NewCollateralFactor(\\n uint96 indexed poolId,\\n VToken indexed vToken,\\n uint256 oldCollateralFactorMantissa,\\n uint256 newCollateralFactorMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive for a market in a pool is changed by admin\\n event NewLiquidationIncentive(\\n uint96 indexed poolId,\\n address indexed vToken,\\n uint256 oldLiquidationIncentiveMantissa,\\n uint256 newLiquidationIncentiveMantissa\\n );\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when VAIController is changed\\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\\n\\n /// @notice Emitted when VAI mint rate is changed by admin\\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\\n\\n /// @notice Emitted when protocol state is changed by admin\\n event ActionProtocolPaused(bool state);\\n\\n /// @notice Emitted when treasury guardian is changed\\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\\n\\n /// @notice Emitted when treasury address is changed\\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\\n\\n /// @notice Emitted when treasury percent is changed\\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\\n\\n /// @notice Emitted when liquidator adress is changed\\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\\n\\n /// @notice Emitted when ComptrollerLens address is changed\\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\\n\\n /// @notice Emitted when VAI Vault info is changed\\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\\n\\n /// @notice Emitted when Venus VAI Vault rate is changed\\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\\n\\n /// @notice Emitted when prime token contract address is changed\\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for all users in a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\\n event IsForcedLiquidationEnabledForUserUpdated(address indexed borrower, address indexed vToken, bool enable);\\n\\n /// @notice Emitted when XVS token address is changed\\n event NewXVSToken(address indexed oldXVS, address indexed newXVS);\\n\\n /// @notice Emitted when XVS vToken address is changed\\n event NewXVSVToken(address indexed oldXVSVToken, address indexed newXVSVToken);\\n\\n /// @notice Emitted when an account's flash loan whitelist status is updated\\n event IsAccountFlashLoanWhitelisted(address indexed account, bool indexed isWhitelisted);\\n\\n /// @notice Emitted when liquidation threshold for a market in a pool is changed by admin\\n event NewLiquidationThreshold(\\n uint96 indexed poolId,\\n VToken indexed vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when the borrowAllowed flag is updated for a market\\n event BorrowAllowedUpdated(uint96 indexed poolId, address indexed market, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when pool active status updated\\n event PoolActiveStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when pool label is updated\\n event PoolLabelUpdated(uint96 indexed poolId, string oldLabel, string newLabel);\\n\\n /// @notice Emitted when pool Fallback status is updated\\n event PoolFallbackStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when flash loan pause status changes\\n event FlashLoanPauseChanged(bool oldPaused, bool newPaused);\\n\\n /**\\n * @notice Compare two addresses to ensure they are different\\n * @param oldAddress The original address to compare\\n * @param newAddress The new address to compare\\n */\\n modifier compareAddress(address oldAddress, address newAddress) {\\n require(oldAddress != newAddress, \\\"old address is same as new address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Compare two values to ensure they are different\\n * @param oldValue The original value to compare\\n * @param newValue The new value to compare\\n */\\n modifier compareValue(uint256 oldValue, uint256 newValue) {\\n require(oldValue != newValue, \\\"old value is same as new value\\\");\\n _;\\n }\\n\\n /**\\n * @notice Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\\n * @param newOracle The new price oracle to set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\\n return __setPriceOracle(newOracle);\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\\n * @param newOracle The new price oracle to set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\\n return __setPriceOracle(newOracle);\\n }\\n\\n /**\\n * @notice Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint256 0=success, otherwise will revert\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\\n return __setCloseFactor(newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint256 0=success, otherwise will revert\\n */\\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\\n return __setCloseFactor(newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Allows the contract admin to set the address of access control of this contract\\n * @param newAccessControlAddress New address for the access control\\n * @return uint256 0=success, otherwise will revert\\n */\\n function _setAccessControl(\\n address newAccessControlAddress\\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(newAccessControlAddress);\\n\\n address oldAccessControlAddress = accessControl;\\n\\n accessControl = newAccessControlAddress;\\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n return __setCollateralFactor(corePoolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\\n }\\n\\n /**\\n * @notice Sets the liquidation incentive for a market in the Core Pool only.\\n * @param vToken The market to set the liquidationIncentive for\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setLiquidationIncentive(\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setLiquidationIncentive(address,uint256)\\\");\\n return __setLiquidationIncentive(corePoolId, vToken, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateral factor and liquidation threshold for a market in the specified pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setCollateralFactor(uint96,address,uint256,uint256)\\\");\\n return __setCollateralFactor(poolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\\n }\\n\\n /**\\n * @notice Sets the liquidation incentive for a market in the specified pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the liquidationIncentive for\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setLiquidationIncentive(uint96,address,uint256)\\\");\\n return __setLiquidationIncentive(poolId, vToken, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Update the address of the liquidator contract\\n * @dev Allows the contract admin to update the address of liquidator contract\\n * @param newLiquidatorContract_ The new address of the liquidator contract\\n */\\n function _setLiquidatorContract(\\n address newLiquidatorContract_\\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(newLiquidatorContract_);\\n address oldLiquidatorContract = liquidatorContract;\\n liquidatorContract = newLiquidatorContract_;\\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @dev Allows the contract admin to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(\\n address newPauseGuardian\\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\\n ensureAdmin();\\n ensureNonzeroAddress(newPauseGuardian);\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\\n */\\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\\n }\\n\\n /**\\n * @notice Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\\n */\\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\\n }\\n\\n /**\\n * @notice Set whole protocol pause/unpause state\\n * @dev Allows a privileged role to pause/unpause protocol\\n * @param state The new state (true=paused, false=unpaused)\\n * @return bool The updated state of the protocol\\n */\\n function _setProtocolPaused(bool state) external returns (bool) {\\n ensureAllowed(\\\"_setProtocolPaused(bool)\\\");\\n\\n protocolPaused = state;\\n emit ActionProtocolPaused(state);\\n return state;\\n }\\n\\n /**\\n * @notice Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\\n * @param markets_ Markets to pause/unpause the actions on\\n * @param actions_ List of action ids to pause/unpause\\n * @param paused_ The new paused state (true=paused, false=unpaused)\\n */\\n function setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\\n __setActionsPaused(markets_, actions_, paused_);\\n }\\n\\n /**\\n * @notice Pause/unpause certain actions\\n * @dev Allows a privileged role to pause/unpause the protocol action state\\n * @param markets_ Markets to pause/unpause the actions on\\n * @param actions_ List of action ids to pause/unpause\\n * @param paused_ The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\\n __setActionsPaused(markets_, actions_, paused_);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function setActionPausedInternal(address market, Action action, bool paused) internal {\\n ensureListed(getCorePoolMarket(market));\\n _actionPaused[market][uint256(action)] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @notice Sets a new VAI controller\\n * @dev Admin function to set a new VAI controller\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setVAIController(\\n VAIControllerInterface vaiController_\\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(address(vaiController_));\\n\\n VAIControllerInterface oldVaiController = vaiController;\\n vaiController = vaiController_;\\n emit NewVAIController(oldVaiController, vaiController_);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the VAI mint rate\\n * @param newVAIMintRate The new VAI mint rate to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setVAIMintRate(\\n uint256 newVAIMintRate\\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n uint256 oldVAIMintRate = vaiMintRate;\\n vaiMintRate = newVAIMintRate;\\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the minted VAI amount of the `owner`\\n * @param owner The address of the account to set\\n * @param amount The amount of VAI to set to the account\\n * @return The number of minted VAI by `owner`\\n */\\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\\n checkProtocolPauseState();\\n\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \\\"VAI is paused\\\");\\n // Check caller is vaiController\\n if (msg.sender != address(vaiController)) {\\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\\n }\\n mintedVAIs[owner] = amount;\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the treasury data.\\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\\n * @param newTreasuryAddress The new address of the treasury to be set\\n * @param newTreasuryPercent The new treasury percent to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256) {\\n // Check caller is admin\\n ensureAdminOr(treasuryGuardian);\\n\\n require(newTreasuryPercent < 1e18, \\\"percent >= 100%\\\");\\n ensureNonzeroAddress(newTreasuryGuardian);\\n ensureNonzeroAddress(newTreasuryAddress);\\n\\n address oldTreasuryGuardian = treasuryGuardian;\\n address oldTreasuryAddress = treasuryAddress;\\n uint256 oldTreasuryPercent = treasuryPercent;\\n\\n treasuryGuardian = newTreasuryGuardian;\\n treasuryAddress = newTreasuryAddress;\\n treasuryPercent = newTreasuryPercent;\\n\\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /*** Venus Distribution ***/\\n\\n /**\\n * @dev Set ComptrollerLens contract address\\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptrollerLens(\\n ComptrollerLensInterface comptrollerLens_\\n ) external virtual compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\\n ensureAdmin();\\n ensureNonzeroAddress(address(comptrollerLens_));\\n address oldComptrollerLens = address(comptrollerLens);\\n comptrollerLens = comptrollerLens_;\\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the amount of XVS distributed per block to VAI Vault\\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\\n */\\n function _setVenusVAIVaultRate(\\n uint256 venusVAIVaultRate_\\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\\n ensureAdmin();\\n if (vaiVaultAddress != address(0)) {\\n releaseToVault();\\n }\\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\\n venusVAIVaultRate = venusVAIVaultRate_;\\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\\n }\\n\\n /**\\n * @notice Set the VAI Vault infos\\n * @param vault_ The address of the VAI Vault\\n * @param releaseStartBlock_ The start block of release to VAI Vault\\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\\n */\\n function _setVAIVaultInfo(\\n address vault_,\\n uint256 releaseStartBlock_,\\n uint256 minReleaseAmount_\\n ) external compareAddress(vaiVaultAddress, vault_) {\\n ensureAdmin();\\n ensureNonzeroAddress(vault_);\\n if (vaiVaultAddress != address(0)) {\\n releaseToVault();\\n }\\n\\n vaiVaultAddress = vault_;\\n releaseStartBlock = releaseStartBlock_;\\n minReleaseAmount = minReleaseAmount_;\\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\\n }\\n\\n /**\\n * @notice Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\\n * @param _prime The new prime token contract to be set\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function setPrimeToken(IPrime _prime) external returns (uint256) {\\n return __setPrimeToken(_prime);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime The new prime token contract to be set\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPrimeToken(IPrime _prime) external returns (uint256) {\\n return __setPrimeToken(_prime);\\n }\\n\\n /**\\n * @notice Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n __setForcedLiquidation(vTokenBorrowed, enable);\\n }\\n\\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @dev Allows a privileged role to set enable/disable forced liquidations\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n __setForcedLiquidation(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for user's borrows in a certain market. If forced\\n * liquidation is enabled, user's borrows in the market may be liquidated regardless of\\n * the account liquidity. Forced liquidation may be enabled for a user even if it is not\\n * enabled for the entire market.\\n * @param borrower The address of the borrower\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external {\\n ensureAllowed(\\\"_setForcedLiquidationForUser(address,address,bool)\\\");\\n if (vTokenBorrowed != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledForUserUpdated(borrower, vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Set the address of the XVS token\\n * @param xvs_ The address of the XVS token\\n */\\n function _setXVSToken(address xvs_) external {\\n ensureAdmin();\\n ensureNonzeroAddress(xvs_);\\n\\n emit NewXVSToken(xvs, xvs_);\\n xvs = xvs_;\\n }\\n\\n /**\\n * @notice Set the address of the XVS vToken\\n * @param xvsVToken_ The address of the XVS vToken\\n */\\n function _setXVSVToken(address xvsVToken_) external {\\n ensureAdmin();\\n ensureNonzeroAddress(xvsVToken_);\\n\\n address underlying = VToken(xvsVToken_).underlying();\\n require(underlying == xvs, \\\"invalid xvs vtoken address\\\");\\n\\n emit NewXVSVToken(xvsVToken, xvsVToken_);\\n xvsVToken = xvsVToken_;\\n }\\n\\n /**\\n * @notice Adds/Removes an account to the flash loan whitelist\\n * @param account The account to authorize for flash loans\\n * @param isWhiteListed True to whitelist the account for flash loans, false to remove from whitelist\\n * @custom:event Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\\n */\\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external {\\n ensureAllowed(\\\"setWhiteListFlashLoanAccount(address,bool)\\\");\\n ensureNonzeroAddress(account);\\n\\n // If the account's status is already the same as the desired status, do nothing\\n if (authorizedFlashLoan[account] == isWhiteListed) {\\n return;\\n }\\n\\n authorizedFlashLoan[account] = isWhiteListed;\\n emit IsAccountFlashLoanWhitelisted(account, isWhiteListed);\\n }\\n\\n /**\\n * @notice Pause or unpause flash loans system-wide\\n * @param paused True to pause flash loans, false to unpause\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanPauseChanged event\\n */\\n function setFlashLoanPaused(bool paused) external {\\n ensureAllowed(\\\"setFlashLoanPaused(bool)\\\");\\n\\n // Check if value is actually changing\\n if (flashLoanPaused == paused) {\\n return; // No change needed\\n }\\n\\n emit FlashLoanPauseChanged(flashLoanPaused, paused);\\n flashLoanPaused = paused;\\n }\\n\\n /**\\n * @notice Updates the label for a specific pool (excluding the Core Pool)\\n * @param poolId ID of the pool to update\\n * @param newLabel The new label for the pool\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist\\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string\\n * @custom:event PoolLabelUpdated Emitted after the pool label is updated\\n */\\n function setPoolLabel(uint96 poolId, string calldata newLabel) external {\\n ensureAllowed(\\\"setPoolLabel(uint96,string)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n if (bytes(newLabel).length == 0) revert EmptyPoolLabel();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (keccak256(bytes(pool.label)) == keccak256(bytes(newLabel))) {\\n return;\\n }\\n\\n emit PoolLabelUpdated(poolId, pool.label, newLabel);\\n pool.label = newLabel;\\n }\\n\\n /**\\n * @notice updates active status for a specific pool (excluding the Core Pool)\\n * @param poolId id of the pool to update\\n * @param active true to enable, false to disable\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:event PoolActiveStatusUpdated Emitted after the pool active status is updated.\\n */\\n function setPoolActive(uint96 poolId, bool active) external {\\n ensureAllowed(\\\"setPoolActive(uint96,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (pool.isActive == active) {\\n return;\\n }\\n\\n emit PoolActiveStatusUpdated(poolId, pool.isActive, active);\\n pool.isActive = active;\\n }\\n\\n /**\\n * @notice Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\\n * @param poolId ID of the pool to update.\\n * @param allowFallback True to allow fallback to Core Pool, false to disable.\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:event PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\\n */\\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external {\\n ensureAllowed(\\\"setAllowCorePoolFallback(uint96,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (pool.allowCorePoolFallback == allowFallback) {\\n return;\\n }\\n\\n emit PoolFallbackStatusUpdated(poolId, pool.allowCorePoolFallback, allowFallback);\\n pool.allowCorePoolFallback = allowFallback;\\n }\\n\\n /**\\n * @notice Updates the `isBorrowAllowed` flag for a market in a pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The address of the market (vToken).\\n * @param borrowAllowed The new borrow allowed status.\\n * @custom:error PoolDoesNotExist Reverts if the pool ID is invalid.\\n * @custom:error MarketConfigNotFound Reverts if the market is not listed in the pool.\\n * @custom:event BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\\n */\\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external {\\n ensureAllowed(\\\"setIsBorrowAllowed(uint96,address,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\\n Market storage m = _poolMarkets[index];\\n\\n if (!m.isListed) {\\n revert MarketConfigNotFound();\\n }\\n\\n if (m.isBorrowAllowed == borrowAllowed) {\\n return;\\n }\\n\\n emit BorrowAllowedUpdated(poolId, vToken, m.isBorrowAllowed, borrowAllowed);\\n m.isBorrowAllowed = borrowAllowed;\\n }\\n\\n /**\\n * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle\\n * @param newOracle The new price oracle to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setPriceOracle(\\n ResilientOracleInterface newOracle\\n ) internal compareAddress(address(oracle), address(newOracle)) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(address(newOracle));\\n\\n // Track the old oracle for the comptroller\\n ResilientOracleInterface oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the close factor. Used by _setCloseFactor and setCloseFactor\\n * @param newCloseFactorMantissa The new close factor to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setCloseFactor(\\n uint256 newCloseFactorMantissa\\n ) internal compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n\\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\\n\\n //-- Check close factor <= 0.9\\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\\n //-- Check close factor >= 0.05\\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\\n\\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the collateral factor and the liquidation threshold. Used by setCollateralFactor\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor to be set\\n * @param newLiquidationThresholdMantissa The new liquidation threshold to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) internal returns (uint256) {\\n ensureNonzeroAddress(address(vToken));\\n\\n // Check if pool exists\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n // Verify market is listed in the pool\\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, address(vToken))];\\n ensureListed(market);\\n\\n //-- Check collateral factor <= 1\\n if (newCollateralFactorMantissa > mantissaOne) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > mantissaOne) {\\n return fail(Error.INVALID_LIQUIDATION_THRESHOLD, FailureInfo.SET_LIQUIDATION_THRESHOLD_VALIDATION);\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n return\\n fail(\\n Error.INVALID_LIQUIDATION_THRESHOLD,\\n FailureInfo.COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n );\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with poolId, asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(poolId, vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n\\n emit NewLiquidationThreshold(\\n poolId,\\n vToken,\\n oldLiquidationThresholdMantissa,\\n newLiquidationThresholdMantissa\\n );\\n }\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the liquidation incentive. Used by setLiquidationIncentive\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the Incentive for\\n * @param newLiquidationIncentiveMantissa The new liquidation incentive to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n )\\n internal\\n compareValue(\\n _poolMarkets[getPoolMarketIndex(poolId, vToken)].liquidationIncentiveMantissa,\\n newLiquidationIncentiveMantissa\\n )\\n returns (uint256)\\n {\\n // Check if pool exists\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n // Verify market is listed in the pool\\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, vToken)];\\n ensureListed(market);\\n\\n require(newLiquidationIncentiveMantissa >= mantissaOne, \\\"incentive < 1e18\\\");\\n\\n emit NewLiquidationIncentive(\\n poolId,\\n vToken,\\n market.liquidationIncentiveMantissa,\\n newLiquidationIncentiveMantissa\\n );\\n\\n // Set liquidation incentive to new incentive\\n market.liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the borrow caps. Used by _setMarketBorrowCaps and setMarketBorrowCaps\\n * @param vTokens The markets to set the borrow caps on\\n * @param newBorrowCaps The new borrow caps to be set\\n */\\n function __setMarketBorrowCaps(VToken[] memory vTokens, uint256[] memory newBorrowCaps) internal {\\n ensureAllowed(\\\"_setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @dev Updates the supply caps. Used by _setMarketSupplyCaps and setMarketSupplyCaps\\n * @param vTokens The markets to set the supply caps on\\n * @param newSupplyCaps The new supply caps to be set\\n */\\n function __setMarketSupplyCaps(VToken[] memory vTokens, uint256[] memory newSupplyCaps) internal {\\n ensureAllowed(\\\"_setMarketSupplyCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numSupplyCaps = newSupplyCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @dev Updates the prime token. Used by _setPrimeToken and setPrimeToken\\n * @param _prime The new prime token to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setPrimeToken(IPrime _prime) internal returns (uint) {\\n ensureAdmin();\\n ensureNonzeroAddress(address(_prime));\\n\\n IPrime oldPrime = prime;\\n prime = _prime;\\n emit NewPrimeToken(oldPrime, _prime);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the forced liquidation. Used by _setForcedLiquidation and setForcedLiquidation\\n * @param vTokenBorrowed The market to set the forced liquidation on\\n * @param enable Whether to enable forced liquidations\\n */\\n function __setForcedLiquidation(address vTokenBorrowed, bool enable) internal {\\n ensureAllowed(\\\"_setForcedLiquidation(address,bool)\\\");\\n if (vTokenBorrowed != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @dev Updates the actions paused. Used by _setActionsPaused and setActionsPaused\\n * @param markets_ The markets to set the actions paused on\\n * @param actions_ The actions to set the paused state on\\n * @param paused_ The new paused state to be set\\n */\\n function __setActionsPaused(address[] memory markets_, Action[] memory actions_, bool paused_) internal {\\n ensureAllowed(\\\"_setActionsPaused(address[],uint8[],bool)\\\");\\n\\n uint256 numMarkets = markets_.length;\\n uint256 numActions = actions_.length;\\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe7cdb06772450e4e6512564266c5830f8a84bdfc8a705c720613b26025f75b5\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../../../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../../../Comptroller/ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../../../Tokens/Prime/IPrime.sol\\\";\\n\\ninterface ISetterFacet {\\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\\n\\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\\n\\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\\n\\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\\n\\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\\n\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256);\\n\\n function setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256);\\n\\n function setLiquidationIncentive(\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256);\\n\\n function setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256);\\n\\n function _setLiquidatorContract(address newLiquidatorContract_) external;\\n\\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\\n\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\\n\\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\\n\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\\n\\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\\n\\n function _setProtocolPaused(bool state) external returns (bool);\\n\\n function setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\\n\\n function _setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\\n\\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\\n\\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\\n\\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\\n\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256);\\n\\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external returns (uint256);\\n\\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\\n\\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\\n\\n function _setForcedLiquidation(address vToken, bool enable) external;\\n\\n function setPrimeToken(IPrime _prime) external returns (uint256);\\n\\n function _setPrimeToken(IPrime _prime) external returns (uint);\\n\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external;\\n\\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external;\\n\\n function _setXVSToken(address xvs_) external;\\n\\n function _setXVSVToken(address xvsVToken_) external;\\n\\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external;\\n\\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external;\\n\\n function setPoolActive(uint96 poolId, bool active) external;\\n\\n function setPoolLabel(uint96 poolId, string calldata newLabel) external;\\n\\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external;\\n\\n function setFlashLoanPaused(bool paused) external;\\n}\\n\",\"keccak256\":\"0xed09149ebd3ab5080875365f39e08f148ca035db8f99af908ce9021b290229c0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b50613c658061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106104bc575f3560e01c80637fb8e8cd11610279578063bec04f7211610156578063dce15449116100ca578063e87554461161008f578063e875544614610b9f578063f445d70314610ba8578063f519fc3014610bd5578063f851a44014610be8578063fa6331d814610bfa578063fd51a3ad14610c03575f80fd5b8063dce1544914610b0d578063dcfbc0c714610b20578063e0f6123d14610b33578063e37d4b7914610b55578063e85a296014610b8c575f80fd5b8063c7ee005e1161011b578063c7ee005e14610aba578063d136af441461072a578063d24febad14610acd578063d3270f9914610ae0578063d463654c14610af3578063d6ad5c3914610afa575f80fd5b8063bec04f7214610a5f578063bf32442d14610a68578063c32094c7146108e9578063c5b4db5514610a79578063c5f956af14610aa7575f80fd5b80639bd8f6e8116101ed578063b2eafc39116101b2578063b2eafc3914610999578063b8324c7c146109ac578063b88d846b14610a07578063bb82aa5e14610a1a578063bb85745014610a2d578063bbb8864a14610a40575f80fd5b80639bd8f6e81461093a5780639bf34cbb1461094d5780639cfdd9e614610960578063a657e57914610973578063a89766dd14610986575f80fd5b8063919a37361161023e578063919a3736146108c35780639254f5e5146108d65780639460c8b5146108e957806394b2294b146108fc57806396c99064146109055780639bb27d6214610927575f80fd5b80637fb8e8cd146108625780638a7dc1651461086f5780638b3113f61461073d5780638c1ac18a1461088e5780639159b177146108b0575f80fd5b806342adb211116103a75780635cc4fdeb1161031b578063719f701b116102e0578063719f701b146107ce57806373769099146107d757806376551383146108175780637938146f146108295780637d172bd51461083c5780637dc0d1d01461084f575f80fd5b80635cc4fdeb146107765780635dd3fc9d146107895780635f5af1aa146107a8578063607ef6c1146105935780636662c7c9146107bb575f80fd5b80634ef233fc1161036c5780634ef233fc1461071757806351a485e41461072a578063522c656b1461073d57806352d84d1e14610750578063530e784f1461076357806355ee1fe114610763575f80fd5b806342adb211146106ac5780634964f48c146106bf5780634a584432146106d25780634d99c776146106f15780634e0853db14610704575f80fd5b806324aaa2201161043e5780632ec04124116104035780632ec041241461063c578063317b0b771461056b578063354392401461064f5780634088c73e1461066257806341a18d2c1461066f578063425fad5814610699575f80fd5b806324aaa220146105e457806326782247146105f75780632a6a60651461060a5780632b5d790c146105e45780632bc7e29e1461061d575f80fd5b806312348e961161048457806312348e961461056b57806317db21631461057e578063186db48f1461059357806321af4569146105a657806324a3d622146105d1575f80fd5b806302c3bcbb146104c057806304ef9d58146104f257806308e0225c146104fb5780630db4b4e51461052557806310b983381461052e575b5f80fd5b6104df6104ce366004613144565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6104df60225481565b6104df61050936600461315f565b601360209081525f928352604080842090915290825290205481565b6104df601d5481565b61055b61053c36600461315f565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016104e9565b6104df610579366004613196565b610c16565b61059161058c3660046131ba565b610c26565b005b6105916105a136600461324a565b610cda565b601e546105b9906001600160a01b031681565b6040516001600160a01b0390911681526020016104e9565b600a546105b9906001600160a01b031681565b6105916105f23660046132b1565b610d4b565b6001546105b9906001600160a01b031681565b61055b61061836600461332f565b610dbf565b6104df61062b366004613144565b60166020525f908152604090205481565b6104df61064a366004613196565b610e55565b6104df61065d366004613365565b610ed8565b60185461055b9060ff1681565b6104df61067d36600461315f565b601260209081525f928352604080842090915290825290205481565b60185461055b9062010000900460ff1681565b6105916106ba3660046133a1565b610f0f565b6105916106cd3660046133cd565b610fb7565b6104df6106e0366004613144565b601f6020525f908152604090205481565b6104df6106ff3660046133e7565b6110ec565b610591610712366004613401565b611109565b610591610725366004613144565b6111cc565b61059161073836600461324a565b6112fa565b61059161074b3660046133a1565b611365565b6105b961075e366004613196565b611373565b6104df610771366004613144565b61139b565b6104df610784366004613401565b6113a5565b6104df610797366004613144565b602b6020525f908152604090205481565b6104df6107b6366004613144565b6113d3565b6105916107c9366004613196565b61146a565b6104df601c5481565b6107ff6107e5366004613144565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016104e9565b60185461055b90610100900460ff1681565b6105916108373660046133cd565b6114f6565b601b546105b9906001600160a01b031681565b6004546105b9906001600160a01b031681565b60395461055b9060ff1681565b6104df61087d366004613144565b60146020525f908152604090205481565b61055b61089c366004613144565b602d6020525f908152604090205460ff1681565b6104df6108be366004613433565b61161d565b6105916108d1366004613144565b611656565b6015546105b9906001600160a01b031681565b6104df6108f7366004613144565b6116c2565b6104df60075481565b610918610913366004613474565b6116cc565b6040516104e9939291906134bb565b6025546105b9906001600160a01b031681565b6104df6109483660046134e4565b611779565b6104df61095b366004613144565b6117a6565b6104df61096e366004613144565b61183c565b6037546107ff906001600160601b031681565b61059161099436600461350e565b6118d3565b6020546105b9906001600160a01b031681565b6109e36109ba366004613144565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104e9565b610591610a15366004613529565b611a14565b6002546105b9906001600160a01b031681565b610591610a3b366004613144565b611b78565b6104df610a4e366004613144565b602a6020525f908152604090205481565b6104df60175481565b6033546001600160a01b03166105b9565b610a8f6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b0390911681526020016104e9565b6021546105b9906001600160a01b031681565b6031546105b9906001600160a01b031681565b6104df610adb3660046135a5565b611c0d565b6026546105b9906001600160a01b031681565b6107ff5f81565b610591610b0836600461332f565b611d74565b6105b9610b1b3660046134e4565b611e1d565b6003546105b9906001600160a01b031681565b61055b610b41366004613144565b60386020525f908152604090205460ff1681565b6109e3610b63366004613144565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61055b610b9a3660046135c2565b611e51565b6104df60055481565b61055b610bb636600461315f565b603260209081525f928352604080842090915290825290205460ff1681565b6104df610be3366004613144565b611e95565b5f546105b9906001600160a01b031681565b6104df601a5481565b6104df610c113660046134e4565b611f2c565b5f610c2082611fd0565b92915050565b610c47604051806060016040528060328152602001613a34603291396120aa565b6015546001600160a01b03838116911614610c6d57610c6d610c688361215a565b61217c565b6001600160a01b038381165f81815260326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fc080966e9e93529edc1b244180c245bc60f3d86f1e690a17651a5e428746a8cd91015b60405180910390a3505050565b610d458484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f920191909152506121c192505050565b50505050565b610db88585808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284375f92019190915250869250612311915050565b5050505050565b5f610dfe6040518060400160405280601881526020017f5f73657450726f746f636f6c50617573656428626f6f6c2900000000000000008152506120aa565b60188054831515620100000262ff0000199091161790556040517fd7500633dd3ddd74daa7af62f8c8404c7fe4a81da179998db851696bed004b3890610e4990841515815260200190565b60405180910390a15090565b5f60175482808203610e825760405162461bcd60e51b8152600401610e79906135f1565b60405180910390fd5b610e8a6123a0565b601780549085905560408051828152602081018790527f73747d68b346dce1e932bcd238282e7ac84c01569e1f8d0469c222fdc6e9d5a491015b60405180910390a15f9350505b5050919050565b5f610efa6040518060600160405280602f8152602001613a8f602f91396120aa565b610f058484846123ec565b90505b9392505050565b610f306040518060600160405280602a8152602001613abe602a91396120aa565b610f398261253e565b6001600160a01b0382165f9081526038602052604090205481151560ff909116151503610f64575050565b6001600160a01b0382165f81815260386020526040808220805460ff191685151590811790915590519092917f1f4df5032f431b9890646a781be28b0d693e581666d1a80be27ae3959069172291a35050565b610ff56040518060400160405280601a81526020017f736574506f6f6c4163746976652875696e7439362c626f6f6c290000000000008152506120aa565b6037546001600160601b03908116908316111561103057604051632db8671b60e11b81526001600160601b0383166004820152602401610e79565b6001600160601b03821661105757604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151560ff90911615150361108757505050565b60028101546040805160ff9092161515825283151560208301526001600160601b038516917f75e42fceb039532886a9d75717e843bfef67fd7f6f91f0fc5b1d48e9ce8a1ba9910160405180910390a2600201805460ff191691151591909117905550565b6001600160a01b031660a09190911b6001600160a01b0319161790565b601b546001600160a01b039081169084908116820361113a5760405162461bcd60e51b8152600401610e799061363c565b6111426123a0565b61114b8561253e565b601b546001600160a01b0316156111645761116461258c565b601b80546001600160a01b0319166001600160a01b038716908117909155601c859055601d84905560408051868152602081018690527f7059037d74ee16b0fb06a4a30f3348dd2635f301f92e373c92899a25a522ef6e910160405180910390a25050505050565b6111d46123a0565b6111dd8161253e565b5f816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561121a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123e919061367e565b6033549091506001600160a01b0380831691161461129e5760405162461bcd60e51b815260206004820152601a60248201527f696e76616c6964207876732076746f6b656e20616464726573730000000000006044820152606401610e79565b6034546040516001600160a01b038085169216907f2565e1579c0926afb7113edbfd85373e85cadaa3e0346f04de19686a2bb86ed1905f90a350603480546001600160a01b0319166001600160a01b0392909216919091179055565b610d458484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f9201919091525061271b92505050565b61136f828261286b565b5050565b600d8181548110611382575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610c208261290b565b5f6113c76040518060600160405280602c8152602001613b34602c91396120aa565b610f055f8585856129a2565b600a545f906001600160a01b03908116908390811682036114065760405162461bcd60e51b8152600401610e799061363c565b61140e6123a0565b6114178461253e565b600a80546001600160a01b038681166001600160a01b03198316179092556040519116907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90610ec49083908890613699565b601a548180820361148d5760405162461bcd60e51b8152600401610e79906135f1565b6114956123a0565b601b546001600160a01b0316156114ae576114ae61258c565b601a80549084905560408051828152602081018690527fe81d4ac15e5afa1e708e66664eddc697177423d950d133bda8262d8885e6da3b91015b60405180910390a150505050565b611517604051806060016040528060258152602001613b89602591396120aa565b6037546001600160601b03908116908316111561155257604051632db8671b60e11b81526001600160601b0383166004820152602401610e79565b6001600160601b03821661157957604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151561010090910460ff161515036115ad57505050565b60028101546040805161010090920460ff161515825283151560208301526001600160601b038516917f9d2a9183b06e3492f91d3d88ae222e700c8873dd0068f9c3fc783eccb96a1ec4910160405180910390a260020180549115156101000261ff001990921691909117905550565b5f61163f604051806060016040528060338152602001613bae603391396120aa565b61164b858585856129a2565b90505b949350505050565b61165e6123a0565b6116678161253e565b6033546040516001600160a01b038084169216907ffe7fd0d872def0f65050e9f38fc6691d0c192c694a56f09b04bec5fb2ea61f2b905f90a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5f610c2082612bbf565b60366020525f90815260409020805481906116e6906136b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611712906136b3565b801561175d5780601f106117345761010080835404028352916020019161175d565b820191905f5260205f20905b81548152906001019060200180831161174057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f61179b604051806060016040528060288152602001613be1602891396120aa565b610f085f84846123ec565b6026545f906001600160a01b03908116908390811682036117d95760405162461bcd60e51b8152600401610e799061363c565b6117e16123a0565b6117ea8461253e565b602680546001600160a01b038681166001600160a01b0319831681179093556040519116917f0f7eb572d1b3053a0a3a33c04151364cf88d163182a5e4e1088cb8e52321e08a91610ec4918491613699565b6015545f906001600160a01b039081169083908116820361186f5760405162461bcd60e51b8152600401610e799061363c565b6118776123a0565b6118808461253e565b601580546001600160a01b038681166001600160a01b03198316179092556040519116907fe1ddcb2dab8e5b03cfc8c67a0d5861d91d16f7bd2612fd381faf4541d212c9b290610ec49083908890613699565b6118f4604051806060016040528060278152602001613c09602791396120aa565b6037546001600160601b03908116908416111561192f57604051632db8671b60e11b81526001600160601b0384166004820152602401610e79565b5f61193a84846110ec565b5f81815260096020526040902080549192509060ff1661196d57604051630665210960e21b815260040160405180910390fd5b82151581600601600c9054906101000a900460ff16151503611990575050505050565b600681015460408051600160601b90920460ff161515825284151560208301526001600160a01b038616916001600160601b038816917fe40f9c4af130bdb5bd1650ab4bc918dba9d900fa94685f0113e72a6cfe6c5fcc910160405180910390a36006018054921515600160601b0260ff60601b1990931692909217909155505050565b611a526040518060400160405280601b81526020017f736574506f6f6c4c6162656c2875696e7439362c737472696e672900000000008152506120aa565b6037546001600160601b039081169084161115611a8d57604051632db8671b60e11b81526001600160601b0384166004820152602401610e79565b6001600160601b038316611ab457604051630203217b60e61b815260040160405180910390fd5b5f819003611ad55760405163522e397360e11b815260040160405180910390fd5b6001600160601b0383165f90815260366020526040908190209051611afd90849084906136eb565b60405190819003812090611b129083906136fa565b604051809103902003611b255750505050565b836001600160601b03167f1ebc260ee8077871ff0b70b184ff9dac4ecee8b0f7dcc4f3a3f5068549f5078e825f018585604051611b6493929190613794565b60405180910390a280610db883858361388b565b6025546001600160a01b0390811690829081168203611ba95760405162461bcd60e51b8152600401610e799061363c565b611bb16123a0565b611bba8361253e565b602580546001600160a01b038581166001600160a01b03198316179092556040519116907fa5ea5616d5f6dbbaa62fdfcf3856723216eed485c394d9e51ec8e6d40e1d1ac1906114e89083908790613699565b6020545f90611c24906001600160a01b0316612c34565b670de0b6b3a76400008210611c6d5760405162461bcd60e51b815260206004820152600f60248201526e70657263656e74203e3d203130302560881b6044820152606401610e79565b611c768461253e565b611c7f8361253e565b6020805460218054602280546001600160a01b03198086166001600160a01b038c8116919091179097558316898716179093558690556040519284169316917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e890611ced9085908a90613699565b60405180910390a17f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac8287604051611d26929190613699565b60405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a15f5b979650505050505050565b611db26040518060400160405280601881526020017f736574466c6173684c6f616e50617573656428626f6f6c2900000000000000008152506120aa565b60395481151560ff909116151503611dc75750565b6039546040805160ff9092161515825282151560208301527f79bcfb2700d56371c7684799f99d64cbcd91f1e360f8048a42c9ba534be7c0a8910160405180910390a16039805460ff1916911515919091179055565b6008602052815f5260405f208181548110611e36575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611e7b57611e7b613628565b815260208101919091526040015f205460ff169392505050565b6028545f906001600160a01b0390811690839081168203611ec85760405162461bcd60e51b8152600401610e799061363c565b611ed06123a0565b611ed98461253e565b602880546001600160a01b038681166001600160a01b03198316179092556040519116907f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd490610ec49083908890613699565b5f611f35612c8f565b60185460ff16158015611f505750601854610100900460ff16155b611f8c5760405162461bcd60e51b815260206004820152600d60248201526c159052481a5cc81c185d5cd959609a1b6044820152606401610e79565b6015546001600160a01b03163314611fb157611faa600e6016612cdd565b9050610c20565b6001600160a01b0383165f908152601660205260408120839055610f08565b5f60055482808203611ff45760405162461bcd60e51b8152600401610e79906135f1565b611ffc6123a0565b604080516020808201835286825282518082018452670c7d713b49da00008152835191820190935266b1a2bc2ec500008152815183519293921080612042575082518151115b1561205c57612052600580612cdd565b9550505050610ed1565b600580549088905560408051828152602081018a90527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9910160405180910390a15f98975050505050505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906120dc9033908590600401613945565b602060405180830381865afa1580156120f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061211b9190613968565b6121575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e79565b50565b5f60095f6121685f856110ec565b81526020019081526020015f209050919050565b805460ff166121575760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e79565b6121e2604051806060016040528060298152602001613b60602991396120aa565b8151815181158015906121f457508082145b6122305760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610e79565b5f5b82811015610db85783818151811061224c5761224c613983565b6020026020010151601f5f87848151811061226957612269613983565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20819055508481815181106122a6576122a6613983565b60200260200101516001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68583815181106122ea576122ea613983565b602002602001015160405161230191815260200190565b60405180910390a2600101612232565b612332604051806060016040528060298152602001613a66602991396120aa565b825182515f5b82811015612398575f5b8281101561238f5761238787838151811061235f5761235f613983565b602002602001015187838151811061237957612379613983565b602002602001015187612d54565b600101612342565b50600101612338565b505050505050565b5f546001600160a01b031633146123ea5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e79565b565b5f60095f6123fa86866110ec565b81526020019081526020015f20600501548280820361242b5760405162461bcd60e51b8152600401610e79906135f1565b6037546001600160601b03908116908716111561246657604051632db8671b60e11b81526001600160601b0387166004820152602401610e79565b5f60095f61247489896110ec565b81526020019081526020015f20905061248c8161217c565b670de0b6b3a76400008510156124d75760405162461bcd60e51b815260206004820152601060248201526f0d2dcc6cadce8d2ecca40784062ca62760831b6044820152606401610e79565b856001600160a01b0316876001600160601b03167fc1d7bc090f3a87255c2f4e56f66d1b7a49683d279f77921b1701aa5d733ef745836005015488604051612529929190918252602082015260400190565b60405180910390a3600581018590555f611d69565b6001600160a01b0381166121575760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610e79565b601c54158061259c5750601c5443105b156125a357565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156125ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126119190613997565b9050805f0361261e575050565b5f8061262c43601c54612df8565b90505f61263b601a5483612e31565b905080841061264c57809250612650565b8392505b601d54831015612661575050505050565b43601c55601b5461267f906001600160a01b03878116911685612e72565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156126fe575f80fd5b505af1158015612710573d5f803e3d5ffd5b505050505050505050565b61273c604051806060016040528060298152602001613ae8602991396120aa565b81518151811580159061274e57508082145b61278a5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610e79565b5f5b82811015610db8578381815181106127a6576127a6613983565b602002602001015160275f8784815181106127c3576127c3613983565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208190555084818151811061280057612800613983565b60200260200101516001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f885838151811061284457612844613983565b602002602001015160405161285b91815260200190565b60405180910390a260010161278c565b61288c604051806060016040528060238152602001613b11602391396120aa565b6015546001600160a01b038381169116146128ad576128ad610c688361215a565b6001600160a01b0382165f818152602d6020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b6004545f906001600160a01b039081169083908116820361293e5760405162461bcd60e51b8152600401610e799061363c565b6129466123a0565b61294f8461253e565b600480546001600160a01b038681166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e2290610ec49083908890613699565b5f6129ac8461253e565b6037546001600160601b0390811690861611156129e757604051632db8671b60e11b81526001600160601b0386166004820152602401610e79565b5f60095f6129f588886110ec565b81526020019081526020015f209050612a0d8161217c565b670de0b6b3a7640000841115612a3157612a2960066008612cdd565b91505061164e565b8315801590612aab57506004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa158015612a85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa99190613997565b155b15612abc57612a29600d6009612cdd565b670de0b6b3a7640000831115612ad857612a2960146019612cdd565b83831015612aec57612a296014601a612cdd565b6001810154848114612b4f576001820185905560408051828152602081018790526001600160a01b038816916001600160601b038a16917f0d1a615379dc62cec7bc63b7e313a07ed659918f4ad3720b3af8041b305146f2910160405180910390a35b6004820154848114612bb2576004830185905560408051828152602081018790526001600160a01b038916916001600160601b038b16917fc90f7b48c299a8d58b0b9e2756e27773c6fb1daab159af052d6c5b791bc7eef7910160405180910390a35b5f98975050505050505050565b5f612bc86123a0565b612bd18261253e565b603180546001600160a01b038481166001600160a01b03198316179092556040519116907fcb20dab7409e4fb972d9adccb39530520b226ce6940d85c9523a499b950b6ea390612c249083908690613699565b60405180910390a15f9392505050565b5f546001600160a01b031633148061211b5750336001600160a01b038216146121575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e79565b60185462010000900460ff16156123ea5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610e79565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836014811115612d1157612d11613628565b83601a811115612d2357612d23613628565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610f0857610f08613628565b612d60610c688461215a565b6001600160a01b0383165f9081526029602052604081208291846008811115612d8b57612d8b613628565b815260208101919091526040015f20805460ff1916911515919091179055816008811115612dbb57612dbb613628565b836001600160a01b03167f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d83604051610ccd911515815260200190565b5f610f088383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612ec9565b5f610f0883836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612ef7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612ec4908490612f50565b505050565b5f8184841115612eec5760405162461bcd60e51b8152600401610e7991906139ae565b50610f0583856139d4565b5f831580612f03575082155b15612f0f57505f610f08565b5f612f1a84866139e7565b905083612f2786836139fe565b148390612f475760405162461bcd60e51b8152600401610e7991906139ae565b50949350505050565b5f612fa4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130239092919063ffffffff16565b905080515f1480612fc4575080806020019051810190612fc49190613968565b612ec45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e79565b6060610f0584845f85855f80866001600160a01b031685876040516130489190613a1d565b5f6040518083038185875af1925050503d805f8114613082576040519150601f19603f3d011682016040523d82523d5f602084013e613087565b606091505b5091509150611d6987838387606083156131015782515f036130fa576001600160a01b0385163b6130fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e79565b508161164e565b61164e83838151156131165781518083602001fd5b8060405162461bcd60e51b8152600401610e7991906139ae565b6001600160a01b0381168114612157575f80fd5b5f60208284031215613154575f80fd5b8135610f0881613130565b5f8060408385031215613170575f80fd5b823561317b81613130565b9150602083013561318b81613130565b809150509250929050565b5f602082840312156131a6575f80fd5b5035919050565b8015158114612157575f80fd5b5f805f606084860312156131cc575f80fd5b83356131d781613130565b925060208401356131e781613130565b915060408401356131f7816131ad565b809150509250925092565b5f8083601f840112613212575f80fd5b50813567ffffffffffffffff811115613229575f80fd5b6020830191508360208260051b8501011115613243575f80fd5b9250929050565b5f805f806040858703121561325d575f80fd5b843567ffffffffffffffff80821115613274575f80fd5b61328088838901613202565b90965094506020870135915080821115613298575f80fd5b506132a587828801613202565b95989497509550505050565b5f805f805f606086880312156132c5575f80fd5b853567ffffffffffffffff808211156132dc575f80fd5b6132e889838a01613202565b90975095506020880135915080821115613300575f80fd5b5061330d88828901613202565b9094509250506040860135613321816131ad565b809150509295509295909350565b5f6020828403121561333f575f80fd5b8135610f08816131ad565b80356001600160601b0381168114613360575f80fd5b919050565b5f805f60608486031215613377575f80fd5b6133808461334a565b9250602084013561339081613130565b929592945050506040919091013590565b5f80604083850312156133b2575f80fd5b82356133bd81613130565b9150602083013561318b816131ad565b5f80604083850312156133de575f80fd5b6133bd8361334a565b5f80604083850312156133f8575f80fd5b61317b8361334a565b5f805f60608486031215613413575f80fd5b833561341e81613130565b95602085013595506040909401359392505050565b5f805f8060808587031215613446575f80fd5b61344f8561334a565b9350602085013561345f81613130565b93969395505050506040820135916060013590565b5f60208284031215613484575f80fd5b610f088261334a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6134cd606083018661348d565b931515602083015250901515604090910152919050565b5f80604083850312156134f5575f80fd5b823561350081613130565b946020939093013593505050565b5f805f60608486031215613520575f80fd5b6131d78461334a565b5f805f6040848603121561353b575f80fd5b6135448461334a565b9250602084013567ffffffffffffffff80821115613560575f80fd5b818601915086601f830112613573575f80fd5b813581811115613581575f80fd5b876020828501011115613592575f80fd5b6020830194508093505050509250925092565b5f805f606084860312156135b7575f80fd5b833561338081613130565b5f80604083850312156135d3575f80fd5b82356135de81613130565b915060208301356009811061318b575f80fd5b6020808252601e908201527f6f6c642076616c75652069732073616d65206173206e65772076616c75650000604082015260600190565b634e487b7160e01b5f52602160045260245ffd5b60208082526022908201527f6f6c6420616464726573732069732073616d65206173206e6577206164647265604082015261737360f01b606082015260800190565b5f6020828403121561368e575f80fd5b8151610f0881613130565b6001600160a01b0392831681529116602082015260400190565b600181811c908216806136c757607f821691505b6020821081036136e557634e487b7160e01b5f52602260045260245ffd5b50919050565b818382375f9101908152919050565b5f808354613707816136b3565b6001828116801561371f576001811461373457613760565b60ff1984168752821515830287019450613760565b875f526020805f205f5b858110156137575781548a82015290840190820161373e565b50505082870194505b50929695505050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f8085546137a5816136b3565b806040860152606060018084165f81146137c657600181146137e257613811565b60ff1985166060890152606084151560051b8901019550613811565b8a5f526020805f205f5b868110156138075781548b82018701529084019082016137ec565b8a01606001975050505b5050505050828103602084015261382981858761376c565b9695505050505050565b634e487b7160e01b5f52604160045260245ffd5b601f821115612ec457805f5260205f20601f840160051c8101602085101561386c5750805b601f840160051c820191505b81811015610db8575f8155600101613878565b67ffffffffffffffff8311156138a3576138a3613833565b6138b7836138b183546136b3565b83613847565b5f601f8411600181146138e8575f85156138d15750838201355b5f19600387901b1c1916600186901b178355610db8565b5f83815260208120601f198716915b8281101561391757868501358255602094850194600190920191016138f7565b5086821015613933575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b03831681526040602082018190525f90610f059083018461348d565b5f60208284031215613978575f80fd5b8151610f08816131ad565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156139a7575f80fd5b5051919050565b602081525f610f08602083018461348d565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c2057610c206139c0565b8082028115828204841417610c2057610c206139c0565b5f82613a1857634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f92019182525091905056fe5f736574466f726365644c69717569646174696f6e466f725573657228616464726573732c616464726573732c626f6f6c295f736574416374696f6e7350617573656428616464726573735b5d2c75696e74385b5d2c626f6f6c297365744c69717569646174696f6e496e63656e746976652875696e7439362c616464726573732c75696e743235362973657457686974654c697374466c6173684c6f616e4163636f756e7428616464726573732c626f6f6c295f7365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d295f736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c29736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e74323536295f7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d29736574416c6c6f77436f7265506f6f6c46616c6c6261636b2875696e7439362c626f6f6c29736574436f6c6c61746572616c466163746f722875696e7439362c616464726573732c75696e743235362c75696e74323536297365744c69717569646174696f6e496e63656e7469766528616464726573732c75696e74323536297365744973426f72726f77416c6c6f7765642875696e7439362c616464726573732c626f6f6c29a2646970667358221220cf038a1331c74b44126bd686f279b2fb27270f9540f7616c7f5746a18eab0c8264736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106104bc575f3560e01c80637fb8e8cd11610279578063bec04f7211610156578063dce15449116100ca578063e87554461161008f578063e875544614610b9f578063f445d70314610ba8578063f519fc3014610bd5578063f851a44014610be8578063fa6331d814610bfa578063fd51a3ad14610c03575f80fd5b8063dce1544914610b0d578063dcfbc0c714610b20578063e0f6123d14610b33578063e37d4b7914610b55578063e85a296014610b8c575f80fd5b8063c7ee005e1161011b578063c7ee005e14610aba578063d136af441461072a578063d24febad14610acd578063d3270f9914610ae0578063d463654c14610af3578063d6ad5c3914610afa575f80fd5b8063bec04f7214610a5f578063bf32442d14610a68578063c32094c7146108e9578063c5b4db5514610a79578063c5f956af14610aa7575f80fd5b80639bd8f6e8116101ed578063b2eafc39116101b2578063b2eafc3914610999578063b8324c7c146109ac578063b88d846b14610a07578063bb82aa5e14610a1a578063bb85745014610a2d578063bbb8864a14610a40575f80fd5b80639bd8f6e81461093a5780639bf34cbb1461094d5780639cfdd9e614610960578063a657e57914610973578063a89766dd14610986575f80fd5b8063919a37361161023e578063919a3736146108c35780639254f5e5146108d65780639460c8b5146108e957806394b2294b146108fc57806396c99064146109055780639bb27d6214610927575f80fd5b80637fb8e8cd146108625780638a7dc1651461086f5780638b3113f61461073d5780638c1ac18a1461088e5780639159b177146108b0575f80fd5b806342adb211116103a75780635cc4fdeb1161031b578063719f701b116102e0578063719f701b146107ce57806373769099146107d757806376551383146108175780637938146f146108295780637d172bd51461083c5780637dc0d1d01461084f575f80fd5b80635cc4fdeb146107765780635dd3fc9d146107895780635f5af1aa146107a8578063607ef6c1146105935780636662c7c9146107bb575f80fd5b80634ef233fc1161036c5780634ef233fc1461071757806351a485e41461072a578063522c656b1461073d57806352d84d1e14610750578063530e784f1461076357806355ee1fe114610763575f80fd5b806342adb211146106ac5780634964f48c146106bf5780634a584432146106d25780634d99c776146106f15780634e0853db14610704575f80fd5b806324aaa2201161043e5780632ec04124116104035780632ec041241461063c578063317b0b771461056b578063354392401461064f5780634088c73e1461066257806341a18d2c1461066f578063425fad5814610699575f80fd5b806324aaa220146105e457806326782247146105f75780632a6a60651461060a5780632b5d790c146105e45780632bc7e29e1461061d575f80fd5b806312348e961161048457806312348e961461056b57806317db21631461057e578063186db48f1461059357806321af4569146105a657806324a3d622146105d1575f80fd5b806302c3bcbb146104c057806304ef9d58146104f257806308e0225c146104fb5780630db4b4e51461052557806310b983381461052e575b5f80fd5b6104df6104ce366004613144565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6104df60225481565b6104df61050936600461315f565b601360209081525f928352604080842090915290825290205481565b6104df601d5481565b61055b61053c36600461315f565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016104e9565b6104df610579366004613196565b610c16565b61059161058c3660046131ba565b610c26565b005b6105916105a136600461324a565b610cda565b601e546105b9906001600160a01b031681565b6040516001600160a01b0390911681526020016104e9565b600a546105b9906001600160a01b031681565b6105916105f23660046132b1565b610d4b565b6001546105b9906001600160a01b031681565b61055b61061836600461332f565b610dbf565b6104df61062b366004613144565b60166020525f908152604090205481565b6104df61064a366004613196565b610e55565b6104df61065d366004613365565b610ed8565b60185461055b9060ff1681565b6104df61067d36600461315f565b601260209081525f928352604080842090915290825290205481565b60185461055b9062010000900460ff1681565b6105916106ba3660046133a1565b610f0f565b6105916106cd3660046133cd565b610fb7565b6104df6106e0366004613144565b601f6020525f908152604090205481565b6104df6106ff3660046133e7565b6110ec565b610591610712366004613401565b611109565b610591610725366004613144565b6111cc565b61059161073836600461324a565b6112fa565b61059161074b3660046133a1565b611365565b6105b961075e366004613196565b611373565b6104df610771366004613144565b61139b565b6104df610784366004613401565b6113a5565b6104df610797366004613144565b602b6020525f908152604090205481565b6104df6107b6366004613144565b6113d3565b6105916107c9366004613196565b61146a565b6104df601c5481565b6107ff6107e5366004613144565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016104e9565b60185461055b90610100900460ff1681565b6105916108373660046133cd565b6114f6565b601b546105b9906001600160a01b031681565b6004546105b9906001600160a01b031681565b60395461055b9060ff1681565b6104df61087d366004613144565b60146020525f908152604090205481565b61055b61089c366004613144565b602d6020525f908152604090205460ff1681565b6104df6108be366004613433565b61161d565b6105916108d1366004613144565b611656565b6015546105b9906001600160a01b031681565b6104df6108f7366004613144565b6116c2565b6104df60075481565b610918610913366004613474565b6116cc565b6040516104e9939291906134bb565b6025546105b9906001600160a01b031681565b6104df6109483660046134e4565b611779565b6104df61095b366004613144565b6117a6565b6104df61096e366004613144565b61183c565b6037546107ff906001600160601b031681565b61059161099436600461350e565b6118d3565b6020546105b9906001600160a01b031681565b6109e36109ba366004613144565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104e9565b610591610a15366004613529565b611a14565b6002546105b9906001600160a01b031681565b610591610a3b366004613144565b611b78565b6104df610a4e366004613144565b602a6020525f908152604090205481565b6104df60175481565b6033546001600160a01b03166105b9565b610a8f6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b0390911681526020016104e9565b6021546105b9906001600160a01b031681565b6031546105b9906001600160a01b031681565b6104df610adb3660046135a5565b611c0d565b6026546105b9906001600160a01b031681565b6107ff5f81565b610591610b0836600461332f565b611d74565b6105b9610b1b3660046134e4565b611e1d565b6003546105b9906001600160a01b031681565b61055b610b41366004613144565b60386020525f908152604090205460ff1681565b6109e3610b63366004613144565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61055b610b9a3660046135c2565b611e51565b6104df60055481565b61055b610bb636600461315f565b603260209081525f928352604080842090915290825290205460ff1681565b6104df610be3366004613144565b611e95565b5f546105b9906001600160a01b031681565b6104df601a5481565b6104df610c113660046134e4565b611f2c565b5f610c2082611fd0565b92915050565b610c47604051806060016040528060328152602001613a34603291396120aa565b6015546001600160a01b03838116911614610c6d57610c6d610c688361215a565b61217c565b6001600160a01b038381165f81815260326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fc080966e9e93529edc1b244180c245bc60f3d86f1e690a17651a5e428746a8cd91015b60405180910390a3505050565b610d458484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f920191909152506121c192505050565b50505050565b610db88585808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284375f92019190915250869250612311915050565b5050505050565b5f610dfe6040518060400160405280601881526020017f5f73657450726f746f636f6c50617573656428626f6f6c2900000000000000008152506120aa565b60188054831515620100000262ff0000199091161790556040517fd7500633dd3ddd74daa7af62f8c8404c7fe4a81da179998db851696bed004b3890610e4990841515815260200190565b60405180910390a15090565b5f60175482808203610e825760405162461bcd60e51b8152600401610e79906135f1565b60405180910390fd5b610e8a6123a0565b601780549085905560408051828152602081018790527f73747d68b346dce1e932bcd238282e7ac84c01569e1f8d0469c222fdc6e9d5a491015b60405180910390a15f9350505b5050919050565b5f610efa6040518060600160405280602f8152602001613a8f602f91396120aa565b610f058484846123ec565b90505b9392505050565b610f306040518060600160405280602a8152602001613abe602a91396120aa565b610f398261253e565b6001600160a01b0382165f9081526038602052604090205481151560ff909116151503610f64575050565b6001600160a01b0382165f81815260386020526040808220805460ff191685151590811790915590519092917f1f4df5032f431b9890646a781be28b0d693e581666d1a80be27ae3959069172291a35050565b610ff56040518060400160405280601a81526020017f736574506f6f6c4163746976652875696e7439362c626f6f6c290000000000008152506120aa565b6037546001600160601b03908116908316111561103057604051632db8671b60e11b81526001600160601b0383166004820152602401610e79565b6001600160601b03821661105757604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151560ff90911615150361108757505050565b60028101546040805160ff9092161515825283151560208301526001600160601b038516917f75e42fceb039532886a9d75717e843bfef67fd7f6f91f0fc5b1d48e9ce8a1ba9910160405180910390a2600201805460ff191691151591909117905550565b6001600160a01b031660a09190911b6001600160a01b0319161790565b601b546001600160a01b039081169084908116820361113a5760405162461bcd60e51b8152600401610e799061363c565b6111426123a0565b61114b8561253e565b601b546001600160a01b0316156111645761116461258c565b601b80546001600160a01b0319166001600160a01b038716908117909155601c859055601d84905560408051868152602081018690527f7059037d74ee16b0fb06a4a30f3348dd2635f301f92e373c92899a25a522ef6e910160405180910390a25050505050565b6111d46123a0565b6111dd8161253e565b5f816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561121a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123e919061367e565b6033549091506001600160a01b0380831691161461129e5760405162461bcd60e51b815260206004820152601a60248201527f696e76616c6964207876732076746f6b656e20616464726573730000000000006044820152606401610e79565b6034546040516001600160a01b038085169216907f2565e1579c0926afb7113edbfd85373e85cadaa3e0346f04de19686a2bb86ed1905f90a350603480546001600160a01b0319166001600160a01b0392909216919091179055565b610d458484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f9201919091525061271b92505050565b61136f828261286b565b5050565b600d8181548110611382575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610c208261290b565b5f6113c76040518060600160405280602c8152602001613b34602c91396120aa565b610f055f8585856129a2565b600a545f906001600160a01b03908116908390811682036114065760405162461bcd60e51b8152600401610e799061363c565b61140e6123a0565b6114178461253e565b600a80546001600160a01b038681166001600160a01b03198316179092556040519116907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90610ec49083908890613699565b601a548180820361148d5760405162461bcd60e51b8152600401610e79906135f1565b6114956123a0565b601b546001600160a01b0316156114ae576114ae61258c565b601a80549084905560408051828152602081018690527fe81d4ac15e5afa1e708e66664eddc697177423d950d133bda8262d8885e6da3b91015b60405180910390a150505050565b611517604051806060016040528060258152602001613b89602591396120aa565b6037546001600160601b03908116908316111561155257604051632db8671b60e11b81526001600160601b0383166004820152602401610e79565b6001600160601b03821661157957604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151561010090910460ff161515036115ad57505050565b60028101546040805161010090920460ff161515825283151560208301526001600160601b038516917f9d2a9183b06e3492f91d3d88ae222e700c8873dd0068f9c3fc783eccb96a1ec4910160405180910390a260020180549115156101000261ff001990921691909117905550565b5f61163f604051806060016040528060338152602001613bae603391396120aa565b61164b858585856129a2565b90505b949350505050565b61165e6123a0565b6116678161253e565b6033546040516001600160a01b038084169216907ffe7fd0d872def0f65050e9f38fc6691d0c192c694a56f09b04bec5fb2ea61f2b905f90a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5f610c2082612bbf565b60366020525f90815260409020805481906116e6906136b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611712906136b3565b801561175d5780601f106117345761010080835404028352916020019161175d565b820191905f5260205f20905b81548152906001019060200180831161174057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f61179b604051806060016040528060288152602001613be1602891396120aa565b610f085f84846123ec565b6026545f906001600160a01b03908116908390811682036117d95760405162461bcd60e51b8152600401610e799061363c565b6117e16123a0565b6117ea8461253e565b602680546001600160a01b038681166001600160a01b0319831681179093556040519116917f0f7eb572d1b3053a0a3a33c04151364cf88d163182a5e4e1088cb8e52321e08a91610ec4918491613699565b6015545f906001600160a01b039081169083908116820361186f5760405162461bcd60e51b8152600401610e799061363c565b6118776123a0565b6118808461253e565b601580546001600160a01b038681166001600160a01b03198316179092556040519116907fe1ddcb2dab8e5b03cfc8c67a0d5861d91d16f7bd2612fd381faf4541d212c9b290610ec49083908890613699565b6118f4604051806060016040528060278152602001613c09602791396120aa565b6037546001600160601b03908116908416111561192f57604051632db8671b60e11b81526001600160601b0384166004820152602401610e79565b5f61193a84846110ec565b5f81815260096020526040902080549192509060ff1661196d57604051630665210960e21b815260040160405180910390fd5b82151581600601600c9054906101000a900460ff16151503611990575050505050565b600681015460408051600160601b90920460ff161515825284151560208301526001600160a01b038616916001600160601b038816917fe40f9c4af130bdb5bd1650ab4bc918dba9d900fa94685f0113e72a6cfe6c5fcc910160405180910390a36006018054921515600160601b0260ff60601b1990931692909217909155505050565b611a526040518060400160405280601b81526020017f736574506f6f6c4c6162656c2875696e7439362c737472696e672900000000008152506120aa565b6037546001600160601b039081169084161115611a8d57604051632db8671b60e11b81526001600160601b0384166004820152602401610e79565b6001600160601b038316611ab457604051630203217b60e61b815260040160405180910390fd5b5f819003611ad55760405163522e397360e11b815260040160405180910390fd5b6001600160601b0383165f90815260366020526040908190209051611afd90849084906136eb565b60405190819003812090611b129083906136fa565b604051809103902003611b255750505050565b836001600160601b03167f1ebc260ee8077871ff0b70b184ff9dac4ecee8b0f7dcc4f3a3f5068549f5078e825f018585604051611b6493929190613794565b60405180910390a280610db883858361388b565b6025546001600160a01b0390811690829081168203611ba95760405162461bcd60e51b8152600401610e799061363c565b611bb16123a0565b611bba8361253e565b602580546001600160a01b038581166001600160a01b03198316179092556040519116907fa5ea5616d5f6dbbaa62fdfcf3856723216eed485c394d9e51ec8e6d40e1d1ac1906114e89083908790613699565b6020545f90611c24906001600160a01b0316612c34565b670de0b6b3a76400008210611c6d5760405162461bcd60e51b815260206004820152600f60248201526e70657263656e74203e3d203130302560881b6044820152606401610e79565b611c768461253e565b611c7f8361253e565b6020805460218054602280546001600160a01b03198086166001600160a01b038c8116919091179097558316898716179093558690556040519284169316917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e890611ced9085908a90613699565b60405180910390a17f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac8287604051611d26929190613699565b60405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a15f5b979650505050505050565b611db26040518060400160405280601881526020017f736574466c6173684c6f616e50617573656428626f6f6c2900000000000000008152506120aa565b60395481151560ff909116151503611dc75750565b6039546040805160ff9092161515825282151560208301527f79bcfb2700d56371c7684799f99d64cbcd91f1e360f8048a42c9ba534be7c0a8910160405180910390a16039805460ff1916911515919091179055565b6008602052815f5260405f208181548110611e36575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611e7b57611e7b613628565b815260208101919091526040015f205460ff169392505050565b6028545f906001600160a01b0390811690839081168203611ec85760405162461bcd60e51b8152600401610e799061363c565b611ed06123a0565b611ed98461253e565b602880546001600160a01b038681166001600160a01b03198316179092556040519116907f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd490610ec49083908890613699565b5f611f35612c8f565b60185460ff16158015611f505750601854610100900460ff16155b611f8c5760405162461bcd60e51b815260206004820152600d60248201526c159052481a5cc81c185d5cd959609a1b6044820152606401610e79565b6015546001600160a01b03163314611fb157611faa600e6016612cdd565b9050610c20565b6001600160a01b0383165f908152601660205260408120839055610f08565b5f60055482808203611ff45760405162461bcd60e51b8152600401610e79906135f1565b611ffc6123a0565b604080516020808201835286825282518082018452670c7d713b49da00008152835191820190935266b1a2bc2ec500008152815183519293921080612042575082518151115b1561205c57612052600580612cdd565b9550505050610ed1565b600580549088905560408051828152602081018a90527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9910160405180910390a15f98975050505050505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906120dc9033908590600401613945565b602060405180830381865afa1580156120f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061211b9190613968565b6121575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e79565b50565b5f60095f6121685f856110ec565b81526020019081526020015f209050919050565b805460ff166121575760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e79565b6121e2604051806060016040528060298152602001613b60602991396120aa565b8151815181158015906121f457508082145b6122305760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610e79565b5f5b82811015610db85783818151811061224c5761224c613983565b6020026020010151601f5f87848151811061226957612269613983565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20819055508481815181106122a6576122a6613983565b60200260200101516001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68583815181106122ea576122ea613983565b602002602001015160405161230191815260200190565b60405180910390a2600101612232565b612332604051806060016040528060298152602001613a66602991396120aa565b825182515f5b82811015612398575f5b8281101561238f5761238787838151811061235f5761235f613983565b602002602001015187838151811061237957612379613983565b602002602001015187612d54565b600101612342565b50600101612338565b505050505050565b5f546001600160a01b031633146123ea5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e79565b565b5f60095f6123fa86866110ec565b81526020019081526020015f20600501548280820361242b5760405162461bcd60e51b8152600401610e79906135f1565b6037546001600160601b03908116908716111561246657604051632db8671b60e11b81526001600160601b0387166004820152602401610e79565b5f60095f61247489896110ec565b81526020019081526020015f20905061248c8161217c565b670de0b6b3a76400008510156124d75760405162461bcd60e51b815260206004820152601060248201526f0d2dcc6cadce8d2ecca40784062ca62760831b6044820152606401610e79565b856001600160a01b0316876001600160601b03167fc1d7bc090f3a87255c2f4e56f66d1b7a49683d279f77921b1701aa5d733ef745836005015488604051612529929190918252602082015260400190565b60405180910390a3600581018590555f611d69565b6001600160a01b0381166121575760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610e79565b601c54158061259c5750601c5443105b156125a357565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156125ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126119190613997565b9050805f0361261e575050565b5f8061262c43601c54612df8565b90505f61263b601a5483612e31565b905080841061264c57809250612650565b8392505b601d54831015612661575050505050565b43601c55601b5461267f906001600160a01b03878116911685612e72565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156126fe575f80fd5b505af1158015612710573d5f803e3d5ffd5b505050505050505050565b61273c604051806060016040528060298152602001613ae8602991396120aa565b81518151811580159061274e57508082145b61278a5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610e79565b5f5b82811015610db8578381815181106127a6576127a6613983565b602002602001015160275f8784815181106127c3576127c3613983565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208190555084818151811061280057612800613983565b60200260200101516001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f885838151811061284457612844613983565b602002602001015160405161285b91815260200190565b60405180910390a260010161278c565b61288c604051806060016040528060238152602001613b11602391396120aa565b6015546001600160a01b038381169116146128ad576128ad610c688361215a565b6001600160a01b0382165f818152602d6020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b6004545f906001600160a01b039081169083908116820361293e5760405162461bcd60e51b8152600401610e799061363c565b6129466123a0565b61294f8461253e565b600480546001600160a01b038681166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e2290610ec49083908890613699565b5f6129ac8461253e565b6037546001600160601b0390811690861611156129e757604051632db8671b60e11b81526001600160601b0386166004820152602401610e79565b5f60095f6129f588886110ec565b81526020019081526020015f209050612a0d8161217c565b670de0b6b3a7640000841115612a3157612a2960066008612cdd565b91505061164e565b8315801590612aab57506004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa158015612a85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa99190613997565b155b15612abc57612a29600d6009612cdd565b670de0b6b3a7640000831115612ad857612a2960146019612cdd565b83831015612aec57612a296014601a612cdd565b6001810154848114612b4f576001820185905560408051828152602081018790526001600160a01b038816916001600160601b038a16917f0d1a615379dc62cec7bc63b7e313a07ed659918f4ad3720b3af8041b305146f2910160405180910390a35b6004820154848114612bb2576004830185905560408051828152602081018790526001600160a01b038916916001600160601b038b16917fc90f7b48c299a8d58b0b9e2756e27773c6fb1daab159af052d6c5b791bc7eef7910160405180910390a35b5f98975050505050505050565b5f612bc86123a0565b612bd18261253e565b603180546001600160a01b038481166001600160a01b03198316179092556040519116907fcb20dab7409e4fb972d9adccb39530520b226ce6940d85c9523a499b950b6ea390612c249083908690613699565b60405180910390a15f9392505050565b5f546001600160a01b031633148061211b5750336001600160a01b038216146121575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e79565b60185462010000900460ff16156123ea5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610e79565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836014811115612d1157612d11613628565b83601a811115612d2357612d23613628565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610f0857610f08613628565b612d60610c688461215a565b6001600160a01b0383165f9081526029602052604081208291846008811115612d8b57612d8b613628565b815260208101919091526040015f20805460ff1916911515919091179055816008811115612dbb57612dbb613628565b836001600160a01b03167f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d83604051610ccd911515815260200190565b5f610f088383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612ec9565b5f610f0883836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612ef7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612ec4908490612f50565b505050565b5f8184841115612eec5760405162461bcd60e51b8152600401610e7991906139ae565b50610f0583856139d4565b5f831580612f03575082155b15612f0f57505f610f08565b5f612f1a84866139e7565b905083612f2786836139fe565b148390612f475760405162461bcd60e51b8152600401610e7991906139ae565b50949350505050565b5f612fa4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130239092919063ffffffff16565b905080515f1480612fc4575080806020019051810190612fc49190613968565b612ec45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e79565b6060610f0584845f85855f80866001600160a01b031685876040516130489190613a1d565b5f6040518083038185875af1925050503d805f8114613082576040519150601f19603f3d011682016040523d82523d5f602084013e613087565b606091505b5091509150611d6987838387606083156131015782515f036130fa576001600160a01b0385163b6130fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e79565b508161164e565b61164e83838151156131165781518083602001fd5b8060405162461bcd60e51b8152600401610e7991906139ae565b6001600160a01b0381168114612157575f80fd5b5f60208284031215613154575f80fd5b8135610f0881613130565b5f8060408385031215613170575f80fd5b823561317b81613130565b9150602083013561318b81613130565b809150509250929050565b5f602082840312156131a6575f80fd5b5035919050565b8015158114612157575f80fd5b5f805f606084860312156131cc575f80fd5b83356131d781613130565b925060208401356131e781613130565b915060408401356131f7816131ad565b809150509250925092565b5f8083601f840112613212575f80fd5b50813567ffffffffffffffff811115613229575f80fd5b6020830191508360208260051b8501011115613243575f80fd5b9250929050565b5f805f806040858703121561325d575f80fd5b843567ffffffffffffffff80821115613274575f80fd5b61328088838901613202565b90965094506020870135915080821115613298575f80fd5b506132a587828801613202565b95989497509550505050565b5f805f805f606086880312156132c5575f80fd5b853567ffffffffffffffff808211156132dc575f80fd5b6132e889838a01613202565b90975095506020880135915080821115613300575f80fd5b5061330d88828901613202565b9094509250506040860135613321816131ad565b809150509295509295909350565b5f6020828403121561333f575f80fd5b8135610f08816131ad565b80356001600160601b0381168114613360575f80fd5b919050565b5f805f60608486031215613377575f80fd5b6133808461334a565b9250602084013561339081613130565b929592945050506040919091013590565b5f80604083850312156133b2575f80fd5b82356133bd81613130565b9150602083013561318b816131ad565b5f80604083850312156133de575f80fd5b6133bd8361334a565b5f80604083850312156133f8575f80fd5b61317b8361334a565b5f805f60608486031215613413575f80fd5b833561341e81613130565b95602085013595506040909401359392505050565b5f805f8060808587031215613446575f80fd5b61344f8561334a565b9350602085013561345f81613130565b93969395505050506040820135916060013590565b5f60208284031215613484575f80fd5b610f088261334a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6134cd606083018661348d565b931515602083015250901515604090910152919050565b5f80604083850312156134f5575f80fd5b823561350081613130565b946020939093013593505050565b5f805f60608486031215613520575f80fd5b6131d78461334a565b5f805f6040848603121561353b575f80fd5b6135448461334a565b9250602084013567ffffffffffffffff80821115613560575f80fd5b818601915086601f830112613573575f80fd5b813581811115613581575f80fd5b876020828501011115613592575f80fd5b6020830194508093505050509250925092565b5f805f606084860312156135b7575f80fd5b833561338081613130565b5f80604083850312156135d3575f80fd5b82356135de81613130565b915060208301356009811061318b575f80fd5b6020808252601e908201527f6f6c642076616c75652069732073616d65206173206e65772076616c75650000604082015260600190565b634e487b7160e01b5f52602160045260245ffd5b60208082526022908201527f6f6c6420616464726573732069732073616d65206173206e6577206164647265604082015261737360f01b606082015260800190565b5f6020828403121561368e575f80fd5b8151610f0881613130565b6001600160a01b0392831681529116602082015260400190565b600181811c908216806136c757607f821691505b6020821081036136e557634e487b7160e01b5f52602260045260245ffd5b50919050565b818382375f9101908152919050565b5f808354613707816136b3565b6001828116801561371f576001811461373457613760565b60ff1984168752821515830287019450613760565b875f526020805f205f5b858110156137575781548a82015290840190820161373e565b50505082870194505b50929695505050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f8085546137a5816136b3565b806040860152606060018084165f81146137c657600181146137e257613811565b60ff1985166060890152606084151560051b8901019550613811565b8a5f526020805f205f5b868110156138075781548b82018701529084019082016137ec565b8a01606001975050505b5050505050828103602084015261382981858761376c565b9695505050505050565b634e487b7160e01b5f52604160045260245ffd5b601f821115612ec457805f5260205f20601f840160051c8101602085101561386c5750805b601f840160051c820191505b81811015610db8575f8155600101613878565b67ffffffffffffffff8311156138a3576138a3613833565b6138b7836138b183546136b3565b83613847565b5f601f8411600181146138e8575f85156138d15750838201355b5f19600387901b1c1916600186901b178355610db8565b5f83815260208120601f198716915b8281101561391757868501358255602094850194600190920191016138f7565b5086821015613933575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b03831681526040602082018190525f90610f059083018461348d565b5f60208284031215613978575f80fd5b8151610f08816131ad565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156139a7575f80fd5b5051919050565b602081525f610f08602083018461348d565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c2057610c206139c0565b8082028115828204841417610c2057610c206139c0565b5f82613a1857634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f92019182525091905056fe5f736574466f726365644c69717569646174696f6e466f725573657228616464726573732c616464726573732c626f6f6c295f736574416374696f6e7350617573656428616464726573735b5d2c75696e74385b5d2c626f6f6c297365744c69717569646174696f6e496e63656e746976652875696e7439362c616464726573732c75696e743235362973657457686974654c697374466c6173684c6f616e4163636f756e7428616464726573732c626f6f6c295f7365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d295f736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c29736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e74323536295f7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d29736574416c6c6f77436f7265506f6f6c46616c6c6261636b2875696e7439362c626f6f6c29736574436f6c6c61746572616c466163746f722875696e7439362c616464726573732c75696e743235362c75696e74323536297365744c69717569646174696f6e496e63656e7469766528616464726573732c75696e74323536297365744973426f72726f77416c6c6f7765642875696e7439362c616464726573732c626f6f6c29a2646970667358221220cf038a1331c74b44126bd686f279b2fb27270f9540f7616c7f5746a18eab0c8264736f6c63430008190033", + "numDeployments": 5, + "solcInputHash": "cbc4287e135101fe4c78448d0f5f2ecc", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPausedMarket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"ActionProtocolPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"BorrowAllowedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldPaused\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newPaused\",\"type\":\"bool\"}],\"name\":\"FlashLoanPauseChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"isWhitelisted\",\"type\":\"bool\"}],\"name\":\"IsAccountFlashLoanWhitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledForUserUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"NewAccessControl\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldComptrollerLens\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newComptrollerLens\",\"type\":\"address\"}],\"name\":\"NewComptrollerLens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"oldDeviationBoundedOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"newDeviationBoundedOracle\",\"type\":\"address\"}],\"name\":\"NewDeviationBoundedOracle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationThresholdMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationThreshold\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldLiquidatorContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newLiquidatorContract\",\"type\":\"address\"}],\"name\":\"NewLiquidatorContract\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IPrime\",\"name\":\"oldPrimeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IPrime\",\"name\":\"newPrimeToken\",\"type\":\"address\"}],\"name\":\"NewPrimeToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSupplyCap\",\"type\":\"uint256\"}],\"name\":\"NewSupplyCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"}],\"name\":\"NewTreasuryAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"}],\"name\":\"NewTreasuryGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldTreasuryPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"NewTreasuryPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract VAIControllerInterface\",\"name\":\"oldVAIController\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract VAIControllerInterface\",\"name\":\"newVAIController\",\"type\":\"address\"}],\"name\":\"NewVAIController\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldVAIMintRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVAIMintRate\",\"type\":\"uint256\"}],\"name\":\"NewVAIMintRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vault_\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartBlock_\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseInterval_\",\"type\":\"uint256\"}],\"name\":\"NewVAIVaultInfo\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldVenusVAIVaultRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVenusVAIVaultRate\",\"type\":\"uint256\"}],\"name\":\"NewVenusVAIVaultRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldXVS\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newXVS\",\"type\":\"address\"}],\"name\":\"NewXVSToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldXVSVToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newXVSVToken\",\"type\":\"address\"}],\"name\":\"NewXVSVToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"PoolActiveStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"PoolFallbackStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"oldLabel\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newLabel\",\"type\":\"string\"}],\"name\":\"PoolLabelUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"_setAccessControl\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets_\",\"type\":\"address[]\"},{\"internalType\":\"enum Action[]\",\"name\":\"actions_\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}],\"name\":\"_setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"comptrollerLens_\",\"type\":\"address\"}],\"name\":\"_setComptrollerLens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"_setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"_setForcedLiquidationForUser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newLiquidatorContract_\",\"type\":\"address\"}],\"name\":\"_setLiquidatorContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_prime\",\"type\":\"address\"}],\"name\":\"_setPrimeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setProtocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"_setTreasuryData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"vaiController_\",\"type\":\"address\"}],\"name\":\"_setVAIController\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newVAIMintRate\",\"type\":\"uint256\"}],\"name\":\"_setVAIMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vault_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"releaseStartBlock_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minReleaseAmount_\",\"type\":\"uint256\"}],\"name\":\"_setVAIVaultInfo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"venusVAIVaultRate_\",\"type\":\"uint256\"}],\"name\":\"_setVenusVAIVaultRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"xvs_\",\"type\":\"address\"}],\"name\":\"_setXVSToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"xvsVToken_\",\"type\":\"address\"}],\"name\":\"_setXVSVToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets_\",\"type\":\"address[]\"},{\"internalType\":\"enum Action[]\",\"name\":\"actions_\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}],\"name\":\"setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"allowFallback\",\"type\":\"bool\"}],\"name\":\"setAllowCorePoolFallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"newDeviationBoundedOracle\",\"type\":\"address\"}],\"name\":\"setDeviationBoundedOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"setFlashLoanPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"borrowAllowed\",\"type\":\"bool\"}],\"name\":\"setIsBorrowAllowed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setMintedVAIOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"}],\"name\":\"setPoolActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"string\",\"name\":\"newLabel\",\"type\":\"string\"}],\"name\":\"setPoolLabel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_prime\",\"type\":\"address\"}],\"name\":\"setPrimeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isWhiteListed\",\"type\":\"bool\"}],\"name\":\"setWhiteListFlashLoanAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the setters for the states\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setAccessControl(address)\":{\"details\":\"Allows the contract admin to set the address of access control of this contract\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"_setActionsPaused(address[],uint8[],bool)\":{\"details\":\"Allows a privileged role to pause/unpause the protocol action state\",\"params\":{\"actions_\":\"List of action ids to pause/unpause\",\"markets_\":\"Markets to pause/unpause the actions on\",\"paused_\":\"The new paused state (true=paused, false=unpaused)\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Allows the contract admin to set the closeFactor used to liquidate borrows\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"_setComptrollerLens(address)\":{\"details\":\"Set ComptrollerLens contract address\",\"params\":{\"comptrollerLens_\":\"The new ComptrollerLens contract address to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setForcedLiquidation(address,bool)\":{\"details\":\"Allows a privileged role to set enable/disable forced liquidations\",\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"_setForcedLiquidationForUser(address,address,bool)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"_setLiquidatorContract(address)\":{\"details\":\"Allows the contract admin to update the address of liquidator contract\",\"params\":{\"newLiquidatorContract_\":\"The new address of the liquidator contract\"}},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\",\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"_setMarketSupplyCaps(address[],uint256[])\":{\"details\":\"Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\",\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"_setPauseGuardian(address)\":{\"details\":\"Allows the contract admin to change the Pause Guardian\",\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"_setPriceOracle(address)\":{\"details\":\"Allows the contract admin to set a new price oracle used by the Comptroller\",\"params\":{\"newOracle\":\"The new price oracle to set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setPrimeToken(address)\":{\"params\":{\"_prime\":\"The new prime token contract to be set\"},\"returns\":{\"_0\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setProtocolPaused(bool)\":{\"details\":\"Allows a privileged role to pause/unpause protocol\",\"params\":{\"state\":\"The new state (true=paused, false=unpaused)\"},\"returns\":{\"_0\":\"bool The updated state of the protocol\"}},\"_setTreasuryData(address,address,uint256)\":{\"params\":{\"newTreasuryAddress\":\"The new address of the treasury to be set\",\"newTreasuryGuardian\":\"The new address of the treasury guardian to be set\",\"newTreasuryPercent\":\"The new treasury percent to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIController(address)\":{\"details\":\"Admin function to set a new VAI controller\",\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIMintRate(uint256)\":{\"params\":{\"newVAIMintRate\":\"The new VAI mint rate to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIVaultInfo(address,uint256,uint256)\":{\"params\":{\"minReleaseAmount_\":\"The minimum release amount to VAI Vault\",\"releaseStartBlock_\":\"The start block of release to VAI Vault\",\"vault_\":\"The address of the VAI Vault\"}},\"_setVenusVAIVaultRate(uint256)\":{\"params\":{\"venusVAIVaultRate_\":\"The amount of XVS wei per block to distribute to VAI Vault\"}},\"_setXVSToken(address)\":{\"params\":{\"xvs_\":\"The address of the XVS token\"}},\"_setXVSVToken(address)\":{\"params\":{\"xvsVToken_\":\"The address of the XVS vToken\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"setActionsPaused(address[],uint8[],bool)\":{\"params\":{\"actions_\":\"List of action ids to pause/unpause\",\"markets_\":\"Markets to pause/unpause the actions on\",\"paused_\":\"The new paused state (true=paused, false=unpaused)\"}},\"setAllowCorePoolFallback(uint96,bool)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.\",\"custom:event\":\"PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\",\"params\":{\"allowFallback\":\"True to allow fallback to Core Pool, false to disable.\",\"poolId\":\"ID of the pool to update.\"}},\"setCloseFactor(uint256)\":{\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"setCollateralFactor(address,uint256,uint256)\":{\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"vToken\":\"The market to set the factor on\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setCollateralFactor(uint96,address,uint256,uint256)\":{\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The market to set the factor on\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setDeviationBoundedOracle(address)\":{\"params\":{\"newDeviationBoundedOracle\":\"The new DeviationBoundedOracle contract\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure\"}},\"setFlashLoanPaused(bool)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits FlashLoanPauseChanged event\",\"params\":{\"paused\":\"True to pause flash loans, false to unpause\"}},\"setForcedLiquidation(address,bool)\":{\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"setIsBorrowAllowed(uint96,address,bool)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the pool ID is invalid.MarketConfigNotFound Reverts if the market is not listed in the pool.\",\"custom:event\":\"BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\",\"params\":{\"borrowAllowed\":\"The new borrow allowed status.\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The address of the market (vToken).\"}},\"setLiquidationIncentive(address,uint256)\":{\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\",\"vToken\":\"The market to set the liquidationIncentive for\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setLiquidationIncentive(uint96,address,uint256)\":{\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The market to set the liquidationIncentive for\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setMarketBorrowCaps(address[],uint256[])\":{\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"setMarketSupplyCaps(address[],uint256[])\":{\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"setMintedVAIOf(address,uint256)\":{\"params\":{\"amount\":\"The amount of VAI to set to the account\",\"owner\":\"The address of the account to set\"},\"returns\":{\"_0\":\"The number of minted VAI by `owner`\"}},\"setPoolActive(uint96,bool)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.\",\"custom:event\":\"PoolActiveStatusUpdated Emitted after the pool active status is updated.\",\"params\":{\"active\":\"true to enable, false to disable\",\"poolId\":\"id of the pool to update\"}},\"setPoolLabel(uint96,string)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core PoolPoolDoesNotExist Reverts if the target pool ID does not existEmptyPoolLabel Reverts if the provided label is an empty string\",\"custom:event\":\"PoolLabelUpdated Emitted after the pool label is updated\",\"params\":{\"newLabel\":\"The new label for the pool\",\"poolId\":\"ID of the pool to update\"}},\"setPriceOracle(address)\":{\"params\":{\"newOracle\":\"The new price oracle to set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"setPrimeToken(address)\":{\"params\":{\"_prime\":\"The new prime token contract to be set\"},\"returns\":{\"_0\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"setWhiteListFlashLoanAccount(address,bool)\":{\"custom:event\":\"Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\",\"params\":{\"account\":\"The account to authorize for flash loans\",\"isWhiteListed\":\"True to whitelist the account for flash loans, false to remove from whitelist\"}}},\"title\":\"SetterFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"ActionPausedMarket(address,uint8,bool)\":{\"notice\":\"Emitted when an action is paused on a market\"},\"ActionProtocolPaused(bool)\":{\"notice\":\"Emitted when protocol state is changed by admin\"},\"BorrowAllowedUpdated(uint96,address,bool,bool)\":{\"notice\":\"Emitted when the borrowAllowed flag is updated for a market\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"FlashLoanPauseChanged(bool,bool)\":{\"notice\":\"Emitted when flash loan pause status changes\"},\"IsAccountFlashLoanWhitelisted(address,bool)\":{\"notice\":\"Emitted when an account's flash loan whitelist status is updated\"},\"IsForcedLiquidationEnabledForUserUpdated(address,address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\"},\"IsForcedLiquidationEnabledUpdated(address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for all users in a market\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"NewAccessControl(address,address)\":{\"notice\":\"Emitted when access control address is changed by admin\"},\"NewBorrowCap(address,uint256)\":{\"notice\":\"Emitted when borrow cap for a vToken is changed\"},\"NewCloseFactor(uint256,uint256)\":{\"notice\":\"Emitted when close factor is changed by admin\"},\"NewCollateralFactor(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when a collateral factor for a market in a pool is changed by admin\"},\"NewComptrollerLens(address,address)\":{\"notice\":\"Emitted when ComptrollerLens address is changed\"},\"NewDeviationBoundedOracle(address,address)\":{\"notice\":\"Emitted when deviation bounded oracle is changed\"},\"NewLiquidationIncentive(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation incentive for a market in a pool is changed by admin\"},\"NewLiquidationThreshold(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation threshold for a market in a pool is changed by admin\"},\"NewLiquidatorContract(address,address)\":{\"notice\":\"Emitted when liquidator adress is changed\"},\"NewPauseGuardian(address,address)\":{\"notice\":\"Emitted when pause guardian is changed\"},\"NewPriceOracle(address,address)\":{\"notice\":\"Emitted when price oracle is changed\"},\"NewPrimeToken(address,address)\":{\"notice\":\"Emitted when prime token contract address is changed\"},\"NewSupplyCap(address,uint256)\":{\"notice\":\"Emitted when supply cap for a vToken is changed\"},\"NewTreasuryAddress(address,address)\":{\"notice\":\"Emitted when treasury address is changed\"},\"NewTreasuryGuardian(address,address)\":{\"notice\":\"Emitted when treasury guardian is changed\"},\"NewTreasuryPercent(uint256,uint256)\":{\"notice\":\"Emitted when treasury percent is changed\"},\"NewVAIController(address,address)\":{\"notice\":\"Emitted when VAIController is changed\"},\"NewVAIMintRate(uint256,uint256)\":{\"notice\":\"Emitted when VAI mint rate is changed by admin\"},\"NewVAIVaultInfo(address,uint256,uint256)\":{\"notice\":\"Emitted when VAI Vault info is changed\"},\"NewVenusVAIVaultRate(uint256,uint256)\":{\"notice\":\"Emitted when Venus VAI Vault rate is changed\"},\"NewXVSToken(address,address)\":{\"notice\":\"Emitted when XVS token address is changed\"},\"NewXVSVToken(address,address)\":{\"notice\":\"Emitted when XVS vToken address is changed\"},\"PoolActiveStatusUpdated(uint96,bool,bool)\":{\"notice\":\"Emitted when pool active status updated\"},\"PoolFallbackStatusUpdated(uint96,bool,bool)\":{\"notice\":\"Emitted when pool Fallback status is updated\"},\"PoolLabelUpdated(uint96,string,string)\":{\"notice\":\"Emitted when pool label is updated\"}},\"kind\":\"user\",\"methods\":{\"_setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"_setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Pause/unpause certain actions\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setForcedLiquidation(address,bool)\":{\"notice\":\"Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity\"},\"_setForcedLiquidationForUser(address,address,bool)\":{\"notice\":\"Enables forced liquidations for user's borrows in a certain market. If forced liquidation is enabled, user's borrows in the market may be liquidated regardless of the account liquidity. Forced liquidation may be enabled for a user even if it is not enabled for the entire market.\"},\"_setLiquidatorContract(address)\":{\"notice\":\"Update the address of the liquidator contract\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\"},\"_setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_setPrimeToken(address)\":{\"notice\":\"Sets the prime token contract for the comptroller\"},\"_setProtocolPaused(bool)\":{\"notice\":\"Set whole protocol pause/unpause state\"},\"_setTreasuryData(address,address,uint256)\":{\"notice\":\"Set the treasury data.\"},\"_setVAIController(address)\":{\"notice\":\"Sets a new VAI controller\"},\"_setVAIMintRate(uint256)\":{\"notice\":\"Set the VAI mint rate\"},\"_setVAIVaultInfo(address,uint256,uint256)\":{\"notice\":\"Set the VAI Vault infos\"},\"_setVenusVAIVaultRate(uint256)\":{\"notice\":\"Set the amount of XVS distributed per block to VAI Vault\"},\"_setXVSToken(address)\":{\"notice\":\"Set the address of the XVS token\"},\"_setXVSVToken(address)\":{\"notice\":\"Set the address of the XVS vToken\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\"},\"setAllowCorePoolFallback(uint96,bool)\":{\"notice\":\"Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\"},\"setCloseFactor(uint256)\":{\"notice\":\"Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\"},\"setCollateralFactor(address,uint256,uint256)\":{\"notice\":\"Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\"},\"setCollateralFactor(uint96,address,uint256,uint256)\":{\"notice\":\"Sets the collateral factor and liquidation threshold for a market in the specified pool.\"},\"setDeviationBoundedOracle(address)\":{\"notice\":\"Sets the DeviationBoundedOracle for conservative CF-path pricing\"},\"setFlashLoanPaused(bool)\":{\"notice\":\"Pause or unpause flash loans system-wide\"},\"setForcedLiquidation(address,bool)\":{\"notice\":\"Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\"},\"setIsBorrowAllowed(uint96,address,bool)\":{\"notice\":\"Updates the `isBorrowAllowed` flag for a market in a pool.\"},\"setLiquidationIncentive(address,uint256)\":{\"notice\":\"Sets the liquidation incentive for a market in the Core Pool only.\"},\"setLiquidationIncentive(uint96,address,uint256)\":{\"notice\":\"Sets the liquidation incentive for a market in the specified pool.\"},\"setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\"},\"setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\"},\"setMintedVAIOf(address,uint256)\":{\"notice\":\"Set the minted VAI amount of the `owner`\"},\"setPoolActive(uint96,bool)\":{\"notice\":\"updates active status for a specific pool (excluding the Core Pool)\"},\"setPoolLabel(uint96,string)\":{\"notice\":\"Updates the label for a specific pool (excluding the Core Pool)\"},\"setPriceOracle(address)\":{\"notice\":\"Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\"},\"setPrimeToken(address)\":{\"notice\":\"Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\"},\"setWhiteListFlashLoanAccount(address,bool)\":{\"notice\":\"Adds/Removes an account to the flash loan whitelist\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains all the configurational setter functions\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/SetterFacet.sol\":\"SetterFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\\n enum KeeperAction {\\n SetMinPrice,\\n SetMaxPrice,\\n ExitProtectionMode\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool cachingEnabled;\\n }\\n\\n /// @notice One item in an syncPriceBoundsAndProtections payload\\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\\n struct KeeperActionItem {\\n address asset;\\n KeeperAction action;\\n uint256 value;\\n }\\n\\n /// @notice One item in a setTokenConfigs payload\\n struct TokenConfigInput {\\n /// @notice The underlying asset address\\n address asset;\\n /// @notice Minimum time protection stays active after the last trigger (seconds)\\n uint64 cooldownPeriod;\\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\\n uint256 triggerThreshold;\\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\\n uint256 resetThreshold;\\n /// @notice Whether to enable bounded pricing immediately upon initialization\\n bool enableBoundedPricing;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool enableCaching;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n /// @notice Emitted when the per-asset transient caching flag is toggled\\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\\n error InvalidKeeperAction(uint8 action);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage. The transient\\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n /**\\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\\n * Empty `actions` is a no-op success.\\n * @param actions The list of keeper actions to apply\\n * @custom:access Only authorized keeper addresses\\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\\n */\\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param tokenConfig_ Token config input for the asset\\n * @custom:access Only Governance\\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param tokenConfigs_ Array of token config inputs, one per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if the input array is empty\\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\\n * @custom:error VAINotAllowed if any asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n /**\\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\\n * live spot instead of reading or writing the transient slots. The initial value is\\n * set via the `enableCaching` argument of `setTokenConfig`.\\n * @param asset The underlying asset address\\n * @param enabled Whether transient caching is enabled for this asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CachingEnabledUpdated\\n */\\n function setCachingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold,\\n bool cachingEnabled\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0xe223d88c17c0d752fdb33fa223b63ce124a798512f3d69f3800e9508e7dff931\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/SetterFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../../ComptrollerLensInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../../../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { IPrime } from \\\"../../../Tokens/Prime/IPrime.sol\\\";\\nimport { ISetterFacet } from \\\"../interfaces/ISetterFacet.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\n/**\\n * @title SetterFacet\\n * @author Venus\\n * @dev This facet contains all the setters for the states\\n * @notice This facet contract contains all the configurational setter functions\\n */\\ncontract SetterFacet is ISetterFacet, FacetBase {\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor for a market in a pool is changed by admin\\n event NewCollateralFactor(\\n uint96 indexed poolId,\\n VToken indexed vToken,\\n uint256 oldCollateralFactorMantissa,\\n uint256 newCollateralFactorMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive for a market in a pool is changed by admin\\n event NewLiquidationIncentive(\\n uint96 indexed poolId,\\n address indexed vToken,\\n uint256 oldLiquidationIncentiveMantissa,\\n uint256 newLiquidationIncentiveMantissa\\n );\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when deviation bounded oracle is changed\\n event NewDeviationBoundedOracle(\\n IDeviationBoundedOracle oldDeviationBoundedOracle,\\n IDeviationBoundedOracle newDeviationBoundedOracle\\n );\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when VAIController is changed\\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\\n\\n /// @notice Emitted when VAI mint rate is changed by admin\\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\\n\\n /// @notice Emitted when protocol state is changed by admin\\n event ActionProtocolPaused(bool state);\\n\\n /// @notice Emitted when treasury guardian is changed\\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\\n\\n /// @notice Emitted when treasury address is changed\\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\\n\\n /// @notice Emitted when treasury percent is changed\\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\\n\\n /// @notice Emitted when liquidator adress is changed\\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\\n\\n /// @notice Emitted when ComptrollerLens address is changed\\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\\n\\n /// @notice Emitted when VAI Vault info is changed\\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\\n\\n /// @notice Emitted when Venus VAI Vault rate is changed\\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\\n\\n /// @notice Emitted when prime token contract address is changed\\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for all users in a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\\n event IsForcedLiquidationEnabledForUserUpdated(address indexed borrower, address indexed vToken, bool enable);\\n\\n /// @notice Emitted when XVS token address is changed\\n event NewXVSToken(address indexed oldXVS, address indexed newXVS);\\n\\n /// @notice Emitted when XVS vToken address is changed\\n event NewXVSVToken(address indexed oldXVSVToken, address indexed newXVSVToken);\\n\\n /// @notice Emitted when an account's flash loan whitelist status is updated\\n event IsAccountFlashLoanWhitelisted(address indexed account, bool indexed isWhitelisted);\\n\\n /// @notice Emitted when liquidation threshold for a market in a pool is changed by admin\\n event NewLiquidationThreshold(\\n uint96 indexed poolId,\\n VToken indexed vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when the borrowAllowed flag is updated for a market\\n event BorrowAllowedUpdated(uint96 indexed poolId, address indexed market, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when pool active status updated\\n event PoolActiveStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when pool label is updated\\n event PoolLabelUpdated(uint96 indexed poolId, string oldLabel, string newLabel);\\n\\n /// @notice Emitted when pool Fallback status is updated\\n event PoolFallbackStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when flash loan pause status changes\\n event FlashLoanPauseChanged(bool oldPaused, bool newPaused);\\n\\n /**\\n * @notice Compare two addresses to ensure they are different\\n * @param oldAddress The original address to compare\\n * @param newAddress The new address to compare\\n */\\n modifier compareAddress(address oldAddress, address newAddress) {\\n require(oldAddress != newAddress, \\\"old address is same as new address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Compare two values to ensure they are different\\n * @param oldValue The original value to compare\\n * @param newValue The new value to compare\\n */\\n modifier compareValue(uint256 oldValue, uint256 newValue) {\\n require(oldValue != newValue, \\\"old value is same as new value\\\");\\n _;\\n }\\n\\n /**\\n * @notice Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\\n * @param newOracle The new price oracle to set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\\n return __setPriceOracle(newOracle);\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\\n * @param newOracle The new price oracle to set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\\n return __setPriceOracle(newOracle);\\n }\\n\\n /**\\n * @notice Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint256 0=success, otherwise will revert\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\\n return __setCloseFactor(newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint256 0=success, otherwise will revert\\n */\\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\\n return __setCloseFactor(newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Allows the contract admin to set the address of access control of this contract\\n * @param newAccessControlAddress New address for the access control\\n * @return uint256 0=success, otherwise will revert\\n */\\n function _setAccessControl(\\n address newAccessControlAddress\\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(newAccessControlAddress);\\n\\n address oldAccessControlAddress = accessControl;\\n\\n accessControl = newAccessControlAddress;\\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n return __setCollateralFactor(corePoolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\\n }\\n\\n /**\\n * @notice Sets the liquidation incentive for a market in the Core Pool only.\\n * @param vToken The market to set the liquidationIncentive for\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setLiquidationIncentive(\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setLiquidationIncentive(address,uint256)\\\");\\n return __setLiquidationIncentive(corePoolId, vToken, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateral factor and liquidation threshold for a market in the specified pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setCollateralFactor(uint96,address,uint256,uint256)\\\");\\n return __setCollateralFactor(poolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\\n }\\n\\n /**\\n * @notice Sets the liquidation incentive for a market in the specified pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the liquidationIncentive for\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setLiquidationIncentive(uint96,address,uint256)\\\");\\n return __setLiquidationIncentive(poolId, vToken, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Update the address of the liquidator contract\\n * @dev Allows the contract admin to update the address of liquidator contract\\n * @param newLiquidatorContract_ The new address of the liquidator contract\\n */\\n function _setLiquidatorContract(\\n address newLiquidatorContract_\\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(newLiquidatorContract_);\\n address oldLiquidatorContract = liquidatorContract;\\n liquidatorContract = newLiquidatorContract_;\\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @dev Allows the contract admin to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(\\n address newPauseGuardian\\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\\n ensureAdmin();\\n ensureNonzeroAddress(newPauseGuardian);\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\\n */\\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\\n }\\n\\n /**\\n * @notice Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\\n */\\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\\n }\\n\\n /**\\n * @notice Set whole protocol pause/unpause state\\n * @dev Allows a privileged role to pause/unpause protocol\\n * @param state The new state (true=paused, false=unpaused)\\n * @return bool The updated state of the protocol\\n */\\n function _setProtocolPaused(bool state) external returns (bool) {\\n ensureAllowed(\\\"_setProtocolPaused(bool)\\\");\\n\\n protocolPaused = state;\\n emit ActionProtocolPaused(state);\\n return state;\\n }\\n\\n /**\\n * @notice Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\\n * @param markets_ Markets to pause/unpause the actions on\\n * @param actions_ List of action ids to pause/unpause\\n * @param paused_ The new paused state (true=paused, false=unpaused)\\n */\\n function setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\\n __setActionsPaused(markets_, actions_, paused_);\\n }\\n\\n /**\\n * @notice Pause/unpause certain actions\\n * @dev Allows a privileged role to pause/unpause the protocol action state\\n * @param markets_ Markets to pause/unpause the actions on\\n * @param actions_ List of action ids to pause/unpause\\n * @param paused_ The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\\n __setActionsPaused(markets_, actions_, paused_);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function setActionPausedInternal(address market, Action action, bool paused) internal {\\n ensureListed(getCorePoolMarket(market));\\n _actionPaused[market][uint256(action)] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @notice Sets a new VAI controller\\n * @dev Admin function to set a new VAI controller\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setVAIController(\\n VAIControllerInterface vaiController_\\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(address(vaiController_));\\n\\n VAIControllerInterface oldVaiController = vaiController;\\n vaiController = vaiController_;\\n emit NewVAIController(oldVaiController, vaiController_);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the VAI mint rate\\n * @param newVAIMintRate The new VAI mint rate to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setVAIMintRate(\\n uint256 newVAIMintRate\\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n uint256 oldVAIMintRate = vaiMintRate;\\n vaiMintRate = newVAIMintRate;\\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the minted VAI amount of the `owner`\\n * @param owner The address of the account to set\\n * @param amount The amount of VAI to set to the account\\n * @return The number of minted VAI by `owner`\\n */\\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\\n checkProtocolPauseState();\\n\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \\\"VAI is paused\\\");\\n // Check caller is vaiController\\n if (msg.sender != address(vaiController)) {\\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\\n }\\n mintedVAIs[owner] = amount;\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the treasury data.\\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\\n * @param newTreasuryAddress The new address of the treasury to be set\\n * @param newTreasuryPercent The new treasury percent to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256) {\\n // Check caller is admin\\n ensureAdminOr(treasuryGuardian);\\n\\n require(newTreasuryPercent < 1e18, \\\"percent >= 100%\\\");\\n ensureNonzeroAddress(newTreasuryGuardian);\\n ensureNonzeroAddress(newTreasuryAddress);\\n\\n address oldTreasuryGuardian = treasuryGuardian;\\n address oldTreasuryAddress = treasuryAddress;\\n uint256 oldTreasuryPercent = treasuryPercent;\\n\\n treasuryGuardian = newTreasuryGuardian;\\n treasuryAddress = newTreasuryAddress;\\n treasuryPercent = newTreasuryPercent;\\n\\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /*** Venus Distribution ***/\\n\\n /**\\n * @dev Set ComptrollerLens contract address\\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptrollerLens(\\n ComptrollerLensInterface comptrollerLens_\\n ) external virtual compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\\n ensureAdmin();\\n ensureNonzeroAddress(address(comptrollerLens_));\\n address oldComptrollerLens = address(comptrollerLens);\\n comptrollerLens = comptrollerLens_;\\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the amount of XVS distributed per block to VAI Vault\\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\\n */\\n function _setVenusVAIVaultRate(\\n uint256 venusVAIVaultRate_\\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\\n ensureAdmin();\\n if (vaiVaultAddress != address(0)) {\\n releaseToVault();\\n }\\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\\n venusVAIVaultRate = venusVAIVaultRate_;\\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\\n }\\n\\n /**\\n * @notice Set the VAI Vault infos\\n * @param vault_ The address of the VAI Vault\\n * @param releaseStartBlock_ The start block of release to VAI Vault\\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\\n */\\n function _setVAIVaultInfo(\\n address vault_,\\n uint256 releaseStartBlock_,\\n uint256 minReleaseAmount_\\n ) external compareAddress(vaiVaultAddress, vault_) {\\n ensureAdmin();\\n ensureNonzeroAddress(vault_);\\n if (vaiVaultAddress != address(0)) {\\n releaseToVault();\\n }\\n\\n vaiVaultAddress = vault_;\\n releaseStartBlock = releaseStartBlock_;\\n minReleaseAmount = minReleaseAmount_;\\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\\n }\\n\\n /**\\n * @notice Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\\n * @param _prime The new prime token contract to be set\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function setPrimeToken(IPrime _prime) external returns (uint256) {\\n return __setPrimeToken(_prime);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime The new prime token contract to be set\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPrimeToken(IPrime _prime) external returns (uint256) {\\n return __setPrimeToken(_prime);\\n }\\n\\n /**\\n * @notice Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n __setForcedLiquidation(vTokenBorrowed, enable);\\n }\\n\\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @dev Allows a privileged role to set enable/disable forced liquidations\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n __setForcedLiquidation(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for user's borrows in a certain market. If forced\\n * liquidation is enabled, user's borrows in the market may be liquidated regardless of\\n * the account liquidity. Forced liquidation may be enabled for a user even if it is not\\n * enabled for the entire market.\\n * @param borrower The address of the borrower\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external {\\n ensureAllowed(\\\"_setForcedLiquidationForUser(address,address,bool)\\\");\\n if (vTokenBorrowed != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledForUserUpdated(borrower, vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Set the address of the XVS token\\n * @param xvs_ The address of the XVS token\\n */\\n function _setXVSToken(address xvs_) external {\\n ensureAdmin();\\n ensureNonzeroAddress(xvs_);\\n\\n emit NewXVSToken(xvs, xvs_);\\n xvs = xvs_;\\n }\\n\\n /**\\n * @notice Set the address of the XVS vToken\\n * @param xvsVToken_ The address of the XVS vToken\\n */\\n function _setXVSVToken(address xvsVToken_) external {\\n ensureAdmin();\\n ensureNonzeroAddress(xvsVToken_);\\n\\n address underlying = VToken(xvsVToken_).underlying();\\n require(underlying == xvs, \\\"invalid xvs vtoken address\\\");\\n\\n emit NewXVSVToken(xvsVToken, xvsVToken_);\\n xvsVToken = xvsVToken_;\\n }\\n\\n /**\\n * @notice Adds/Removes an account to the flash loan whitelist\\n * @param account The account to authorize for flash loans\\n * @param isWhiteListed True to whitelist the account for flash loans, false to remove from whitelist\\n * @custom:event Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\\n */\\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external {\\n ensureAllowed(\\\"setWhiteListFlashLoanAccount(address,bool)\\\");\\n ensureNonzeroAddress(account);\\n\\n // If the account's status is already the same as the desired status, do nothing\\n if (authorizedFlashLoan[account] == isWhiteListed) {\\n return;\\n }\\n\\n authorizedFlashLoan[account] = isWhiteListed;\\n emit IsAccountFlashLoanWhitelisted(account, isWhiteListed);\\n }\\n\\n /**\\n * @notice Pause or unpause flash loans system-wide\\n * @param paused True to pause flash loans, false to unpause\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanPauseChanged event\\n */\\n function setFlashLoanPaused(bool paused) external {\\n ensureAllowed(\\\"setFlashLoanPaused(bool)\\\");\\n\\n // Check if value is actually changing\\n if (flashLoanPaused == paused) {\\n return; // No change needed\\n }\\n\\n emit FlashLoanPauseChanged(flashLoanPaused, paused);\\n flashLoanPaused = paused;\\n }\\n\\n /**\\n * @notice Updates the label for a specific pool (excluding the Core Pool)\\n * @param poolId ID of the pool to update\\n * @param newLabel The new label for the pool\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist\\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string\\n * @custom:event PoolLabelUpdated Emitted after the pool label is updated\\n */\\n function setPoolLabel(uint96 poolId, string calldata newLabel) external {\\n ensureAllowed(\\\"setPoolLabel(uint96,string)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n if (bytes(newLabel).length == 0) revert EmptyPoolLabel();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (keccak256(bytes(pool.label)) == keccak256(bytes(newLabel))) {\\n return;\\n }\\n\\n emit PoolLabelUpdated(poolId, pool.label, newLabel);\\n pool.label = newLabel;\\n }\\n\\n /**\\n * @notice updates active status for a specific pool (excluding the Core Pool)\\n * @param poolId id of the pool to update\\n * @param active true to enable, false to disable\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:event PoolActiveStatusUpdated Emitted after the pool active status is updated.\\n */\\n function setPoolActive(uint96 poolId, bool active) external {\\n ensureAllowed(\\\"setPoolActive(uint96,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (pool.isActive == active) {\\n return;\\n }\\n\\n emit PoolActiveStatusUpdated(poolId, pool.isActive, active);\\n pool.isActive = active;\\n }\\n\\n /**\\n * @notice Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\\n * @param poolId ID of the pool to update.\\n * @param allowFallback True to allow fallback to Core Pool, false to disable.\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:event PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\\n */\\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external {\\n ensureAllowed(\\\"setAllowCorePoolFallback(uint96,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (pool.allowCorePoolFallback == allowFallback) {\\n return;\\n }\\n\\n emit PoolFallbackStatusUpdated(poolId, pool.allowCorePoolFallback, allowFallback);\\n pool.allowCorePoolFallback = allowFallback;\\n }\\n\\n /**\\n * @notice Updates the `isBorrowAllowed` flag for a market in a pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The address of the market (vToken).\\n * @param borrowAllowed The new borrow allowed status.\\n * @custom:error PoolDoesNotExist Reverts if the pool ID is invalid.\\n * @custom:error MarketConfigNotFound Reverts if the market is not listed in the pool.\\n * @custom:event BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\\n */\\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external {\\n ensureAllowed(\\\"setIsBorrowAllowed(uint96,address,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\\n Market storage m = _poolMarkets[index];\\n\\n if (!m.isListed) {\\n revert MarketConfigNotFound();\\n }\\n\\n if (m.isBorrowAllowed == borrowAllowed) {\\n return;\\n }\\n\\n emit BorrowAllowedUpdated(poolId, vToken, m.isBorrowAllowed, borrowAllowed);\\n m.isBorrowAllowed = borrowAllowed;\\n }\\n\\n /**\\n * @notice Sets the DeviationBoundedOracle for conservative CF-path pricing\\n * @param newDeviationBoundedOracle The new DeviationBoundedOracle contract\\n * @return uint256 0=success, otherwise a failure\\n */\\n function setDeviationBoundedOracle(\\n IDeviationBoundedOracle newDeviationBoundedOracle\\n ) external compareAddress(address(deviationBoundedOracle), address(newDeviationBoundedOracle)) returns (uint256) {\\n ensureAllowed(\\\"setDeviationBoundedOracle(address)\\\");\\n\\n ensureNonzeroAddress(address(newDeviationBoundedOracle));\\n\\n IDeviationBoundedOracle oldDeviationBoundedOracle = deviationBoundedOracle;\\n deviationBoundedOracle = newDeviationBoundedOracle;\\n\\n emit NewDeviationBoundedOracle(oldDeviationBoundedOracle, newDeviationBoundedOracle);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle\\n * @param newOracle The new price oracle to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setPriceOracle(\\n ResilientOracleInterface newOracle\\n ) internal compareAddress(address(oracle), address(newOracle)) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(address(newOracle));\\n\\n // Track the old oracle for the comptroller\\n ResilientOracleInterface oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the close factor. Used by _setCloseFactor and setCloseFactor\\n * @param newCloseFactorMantissa The new close factor to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setCloseFactor(\\n uint256 newCloseFactorMantissa\\n ) internal compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n\\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\\n\\n //-- Check close factor <= 0.9\\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\\n //-- Check close factor >= 0.05\\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\\n\\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the collateral factor and the liquidation threshold. Used by setCollateralFactor\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor to be set\\n * @param newLiquidationThresholdMantissa The new liquidation threshold to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) internal returns (uint256) {\\n ensureNonzeroAddress(address(vToken));\\n\\n // Check if pool exists\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n // Verify market is listed in the pool\\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, address(vToken))];\\n ensureListed(market);\\n\\n //-- Check collateral factor <= 1\\n if (newCollateralFactorMantissa > mantissaOne) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > mantissaOne) {\\n return fail(Error.INVALID_LIQUIDATION_THRESHOLD, FailureInfo.SET_LIQUIDATION_THRESHOLD_VALIDATION);\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n return\\n fail(\\n Error.INVALID_LIQUIDATION_THRESHOLD,\\n FailureInfo.COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n );\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with poolId, asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(poolId, vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n\\n emit NewLiquidationThreshold(\\n poolId,\\n vToken,\\n oldLiquidationThresholdMantissa,\\n newLiquidationThresholdMantissa\\n );\\n }\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the liquidation incentive. Used by setLiquidationIncentive\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the Incentive for\\n * @param newLiquidationIncentiveMantissa The new liquidation incentive to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n )\\n internal\\n compareValue(\\n _poolMarkets[getPoolMarketIndex(poolId, vToken)].liquidationIncentiveMantissa,\\n newLiquidationIncentiveMantissa\\n )\\n returns (uint256)\\n {\\n // Check if pool exists\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n // Verify market is listed in the pool\\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, vToken)];\\n ensureListed(market);\\n\\n require(newLiquidationIncentiveMantissa >= mantissaOne, \\\"incentive < 1e18\\\");\\n\\n emit NewLiquidationIncentive(\\n poolId,\\n vToken,\\n market.liquidationIncentiveMantissa,\\n newLiquidationIncentiveMantissa\\n );\\n\\n // Set liquidation incentive to new incentive\\n market.liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the borrow caps. Used by _setMarketBorrowCaps and setMarketBorrowCaps\\n * @param vTokens The markets to set the borrow caps on\\n * @param newBorrowCaps The new borrow caps to be set\\n */\\n function __setMarketBorrowCaps(VToken[] memory vTokens, uint256[] memory newBorrowCaps) internal {\\n ensureAllowed(\\\"_setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @dev Updates the supply caps. Used by _setMarketSupplyCaps and setMarketSupplyCaps\\n * @param vTokens The markets to set the supply caps on\\n * @param newSupplyCaps The new supply caps to be set\\n */\\n function __setMarketSupplyCaps(VToken[] memory vTokens, uint256[] memory newSupplyCaps) internal {\\n ensureAllowed(\\\"_setMarketSupplyCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numSupplyCaps = newSupplyCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @dev Updates the prime token. Used by _setPrimeToken and setPrimeToken\\n * @param _prime The new prime token to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setPrimeToken(IPrime _prime) internal returns (uint) {\\n ensureAdmin();\\n ensureNonzeroAddress(address(_prime));\\n\\n IPrime oldPrime = prime;\\n prime = _prime;\\n emit NewPrimeToken(oldPrime, _prime);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the forced liquidation. Used by _setForcedLiquidation and setForcedLiquidation\\n * @param vTokenBorrowed The market to set the forced liquidation on\\n * @param enable Whether to enable forced liquidations\\n */\\n function __setForcedLiquidation(address vTokenBorrowed, bool enable) internal {\\n ensureAllowed(\\\"_setForcedLiquidation(address,bool)\\\");\\n if (vTokenBorrowed != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @dev Updates the actions paused. Used by _setActionsPaused and setActionsPaused\\n * @param markets_ The markets to set the actions paused on\\n * @param actions_ The actions to set the paused state on\\n * @param paused_ The new paused state to be set\\n */\\n function __setActionsPaused(address[] memory markets_, Action[] memory actions_, bool paused_) internal {\\n ensureAllowed(\\\"_setActionsPaused(address[],uint8[],bool)\\\");\\n\\n uint256 numMarkets = markets_.length;\\n uint256 numActions = actions_.length;\\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x97c8edf14a752732fbf1e8cc4fc4aeca6dd83d56a048d9ed4a17ac06135d613a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../../../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../../../Comptroller/ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../../../Tokens/Prime/IPrime.sol\\\";\\n\\ninterface ISetterFacet {\\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\\n\\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\\n\\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\\n\\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\\n\\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\\n\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256);\\n\\n function setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256);\\n\\n function setLiquidationIncentive(\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256);\\n\\n function setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256);\\n\\n function _setLiquidatorContract(address newLiquidatorContract_) external;\\n\\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\\n\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\\n\\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\\n\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\\n\\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\\n\\n function _setProtocolPaused(bool state) external returns (bool);\\n\\n function setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\\n\\n function _setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\\n\\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\\n\\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\\n\\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\\n\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256);\\n\\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external returns (uint256);\\n\\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\\n\\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\\n\\n function _setForcedLiquidation(address vToken, bool enable) external;\\n\\n function setPrimeToken(IPrime _prime) external returns (uint256);\\n\\n function _setPrimeToken(IPrime _prime) external returns (uint);\\n\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external;\\n\\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external;\\n\\n function _setXVSToken(address xvs_) external;\\n\\n function _setXVSVToken(address xvsVToken_) external;\\n\\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external;\\n\\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external;\\n\\n function setPoolActive(uint96 poolId, bool active) external;\\n\\n function setPoolLabel(uint96 poolId, string calldata newLabel) external;\\n\\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external;\\n\\n function setFlashLoanPaused(bool paused) external;\\n\\n function setDeviationBoundedOracle(IDeviationBoundedOracle newDeviationBoundedOracle) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xd29980800653e500a3a995cbc30cd00c6074c5204c86426bd28d4e23e18dba8a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b50613d878061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106104d2575f3560e01c80638a7dc16511610284578063bf32442d11610161578063dce15449116100d5578063f445d7031161008f578063f445d70314610bd6578063f519fc3014610c03578063f851a44014610c16578063fa6331d814610c28578063fd51a3ad14610c31578063fe40768f14610c44575f80fd5b8063dce1544914610b3b578063dcfbc0c714610b4e578063e0f6123d14610b61578063e37d4b7914610b83578063e85a296014610bba578063e875544614610bcd575f80fd5b8063d136af4411610126578063d136af4414610740578063d24febad14610ae3578063d3270f9914610af6578063d463654c14610b09578063d6ad5c3914610b10578063d7c46d2d14610b23575f80fd5b8063bf32442d14610a7e578063c32094c7146108ff578063c5b4db5514610a8f578063c5f956af14610abd578063c7ee005e14610ad0575f80fd5b80639bf34cbb116101f8578063b8324c7c116101bd578063b8324c7c146109c2578063b88d846b14610a1d578063bb82aa5e14610a30578063bb85745014610a43578063bbb8864a14610a56578063bec04f7214610a75575f80fd5b80639bf34cbb146109635780639cfdd9e614610976578063a657e57914610989578063a89766dd1461099c578063b2eafc39146109af575f80fd5b80639254f5e5116102495780639254f5e5146108ec5780639460c8b5146108ff57806394b2294b1461091257806396c990641461091b5780639bb27d621461093d5780639bd8f6e814610950575f80fd5b80638a7dc165146108855780638b3113f6146107535780638c1ac18a146108a45780639159b177146108c6578063919a3736146108d9575f80fd5b80634964f48c116103b25780635dd3fc9d1161032657806373769099116102eb57806373769099146107ed578063765513831461082d5780637938146f1461083f5780637d172bd5146108525780637dc0d1d0146108655780637fb8e8cd14610878575f80fd5b80635dd3fc9d1461079f5780635f5af1aa146107be578063607ef6c1146105a95780636662c7c9146107d1578063719f701b146107e4575f80fd5b806351a485e41161037757806351a485e414610740578063522c656b1461075357806352d84d1e14610766578063530e784f1461077957806355ee1fe1146107795780635cc4fdeb1461078c575f80fd5b80634964f48c146106d55780634a584432146106e85780634d99c776146107075780634e0853db1461071a5780634ef233fc1461072d575f80fd5b80632678224711610449578063317b0b771161040e578063317b0b771461058157806335439240146106655780634088c73e1461067857806341a18d2c14610685578063425fad58146106af57806342adb211146106c2575f80fd5b8063267822471461060d5780632a6a6065146106205780632b5d790c146105fa5780632bc7e29e146106335780632ec0412414610652575f80fd5b806312348e961161049a57806312348e961461058157806317db216314610594578063186db48f146105a957806321af4569146105bc57806324a3d622146105e757806324aaa220146105fa575f80fd5b806302c3bcbb146104d657806304ef9d581461050857806308e0225c146105115780630db4b4e51461053b57806310b9833814610544575b5f80fd5b6104f56104e4366004613244565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6104f560225481565b6104f561051f36600461325f565b601360209081525f928352604080842090915290825290205481565b6104f5601d5481565b61057161055236600461325f565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016104ff565b6104f561058f366004613296565b610c57565b6105a76105a23660046132ba565b610c67565b005b6105a76105b736600461334a565b610d1b565b601e546105cf906001600160a01b031681565b6040516001600160a01b0390911681526020016104ff565b600a546105cf906001600160a01b031681565b6105a76106083660046133b1565b610d8c565b6001546105cf906001600160a01b031681565b61057161062e36600461342f565b610e00565b6104f5610641366004613244565b60166020525f908152604090205481565b6104f5610660366004613296565b610e96565b6104f5610673366004613465565b610f19565b6018546105719060ff1681565b6104f561069336600461325f565b601260209081525f928352604080842090915290825290205481565b6018546105719062010000900460ff1681565b6105a76106d03660046134a1565b610f50565b6105a76106e33660046134cd565b610ff8565b6104f56106f6366004613244565b601f6020525f908152604090205481565b6104f56107153660046134e7565b61112d565b6105a7610728366004613501565b61114a565b6105a761073b366004613244565b61120d565b6105a761074e36600461334a565b61133b565b6105a76107613660046134a1565b6113a6565b6105cf610774366004613296565b6113b4565b6104f5610787366004613244565b6113dc565b6104f561079a366004613501565b6113e6565b6104f56107ad366004613244565b602b6020525f908152604090205481565b6104f56107cc366004613244565b611414565b6105a76107df366004613296565b6114ab565b6104f5601c5481565b6108156107fb366004613244565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016104ff565b60185461057190610100900460ff1681565b6105a761084d3660046134cd565b611537565b601b546105cf906001600160a01b031681565b6004546105cf906001600160a01b031681565b6039546105719060ff1681565b6104f5610893366004613244565b60146020525f908152604090205481565b6105716108b2366004613244565b602d6020525f908152604090205460ff1681565b6104f56108d4366004613533565b61165e565b6105a76108e7366004613244565b611697565b6015546105cf906001600160a01b031681565b6104f561090d366004613244565b611703565b6104f560075481565b61092e610929366004613574565b61170d565b6040516104ff939291906135bb565b6025546105cf906001600160a01b031681565b6104f561095e3660046135e4565b6117ba565b6104f5610971366004613244565b6117e7565b6104f5610984366004613244565b61187d565b603754610815906001600160601b031681565b6105a76109aa36600461360e565b611914565b6020546105cf906001600160a01b031681565b6109f96109d0366004613244565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104ff565b6105a7610a2b366004613629565b611a55565b6002546105cf906001600160a01b031681565b6105a7610a51366004613244565b611bb9565b6104f5610a64366004613244565b602a6020525f908152604090205481565b6104f560175481565b6033546001600160a01b03166105cf565b610aa56ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b0390911681526020016104ff565b6021546105cf906001600160a01b031681565b6031546105cf906001600160a01b031681565b6104f5610af13660046136a5565b611c4e565b6026546105cf906001600160a01b031681565b6108155f81565b6105a7610b1e36600461342f565b611db5565b6039546105cf9061010090046001600160a01b031681565b6105cf610b493660046135e4565b611e5e565b6003546105cf906001600160a01b031681565b610571610b6f366004613244565b60386020525f908152604090205460ff1681565b6109f9610b91366004613244565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b610571610bc83660046136c2565b611e92565b6104f560055481565b610571610be436600461325f565b603260209081525f928352604080842090915290825290205460ff1681565b6104f5610c11366004613244565b611ed6565b5f546105cf906001600160a01b031681565b6104f5601a5481565b6104f5610c3f3660046135e4565b611f6d565b6104f5610c52366004613244565b612011565b5f610c61826120d0565b92915050565b610c88604051806060016040528060328152602001613b34603291396121aa565b6015546001600160a01b03838116911614610cae57610cae610ca98361225a565b61227c565b6001600160a01b038381165f81815260326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fc080966e9e93529edc1b244180c245bc60f3d86f1e690a17651a5e428746a8cd91015b60405180910390a3505050565b610d868484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f920191909152506122c192505050565b50505050565b610df98585808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284375f92019190915250869250612411915050565b5050505050565b5f610e3f6040518060400160405280601881526020017f5f73657450726f746f636f6c50617573656428626f6f6c2900000000000000008152506121aa565b60188054831515620100000262ff0000199091161790556040517fd7500633dd3ddd74daa7af62f8c8404c7fe4a81da179998db851696bed004b3890610e8a90841515815260200190565b60405180910390a15090565b5f60175482808203610ec35760405162461bcd60e51b8152600401610eba906136f1565b60405180910390fd5b610ecb6124a0565b601780549085905560408051828152602081018790527f73747d68b346dce1e932bcd238282e7ac84c01569e1f8d0469c222fdc6e9d5a491015b60405180910390a15f9350505b5050919050565b5f610f3b6040518060600160405280602f8152602001613b8f602f91396121aa565b610f468484846124ec565b90505b9392505050565b610f716040518060600160405280602a8152602001613bbe602a91396121aa565b610f7a8261263e565b6001600160a01b0382165f9081526038602052604090205481151560ff909116151503610fa5575050565b6001600160a01b0382165f81815260386020526040808220805460ff191685151590811790915590519092917f1f4df5032f431b9890646a781be28b0d693e581666d1a80be27ae3959069172291a35050565b6110366040518060400160405280601a81526020017f736574506f6f6c4163746976652875696e7439362c626f6f6c290000000000008152506121aa565b6037546001600160601b03908116908316111561107157604051632db8671b60e11b81526001600160601b0383166004820152602401610eba565b6001600160601b03821661109857604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151560ff9091161515036110c857505050565b60028101546040805160ff9092161515825283151560208301526001600160601b038516917f75e42fceb039532886a9d75717e843bfef67fd7f6f91f0fc5b1d48e9ce8a1ba9910160405180910390a2600201805460ff191691151591909117905550565b6001600160a01b031660a09190911b6001600160a01b0319161790565b601b546001600160a01b039081169084908116820361117b5760405162461bcd60e51b8152600401610eba9061373c565b6111836124a0565b61118c8561263e565b601b546001600160a01b0316156111a5576111a561268c565b601b80546001600160a01b0319166001600160a01b038716908117909155601c859055601d84905560408051868152602081018690527f7059037d74ee16b0fb06a4a30f3348dd2635f301f92e373c92899a25a522ef6e910160405180910390a25050505050565b6112156124a0565b61121e8161263e565b5f816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061127f919061377e565b6033549091506001600160a01b038083169116146112df5760405162461bcd60e51b815260206004820152601a60248201527f696e76616c6964207876732076746f6b656e20616464726573730000000000006044820152606401610eba565b6034546040516001600160a01b038085169216907f2565e1579c0926afb7113edbfd85373e85cadaa3e0346f04de19686a2bb86ed1905f90a350603480546001600160a01b0319166001600160a01b0392909216919091179055565b610d868484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f9201919091525061281b92505050565b6113b0828261296b565b5050565b600d81815481106113c3575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610c6182612a0b565b5f6114086040518060600160405280602c8152602001613c34602c91396121aa565b610f465f858585612aa2565b600a545f906001600160a01b03908116908390811682036114475760405162461bcd60e51b8152600401610eba9061373c565b61144f6124a0565b6114588461263e565b600a80546001600160a01b038681166001600160a01b03198316179092556040519116907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90610f059083908890613799565b601a54818082036114ce5760405162461bcd60e51b8152600401610eba906136f1565b6114d66124a0565b601b546001600160a01b0316156114ef576114ef61268c565b601a80549084905560408051828152602081018690527fe81d4ac15e5afa1e708e66664eddc697177423d950d133bda8262d8885e6da3b91015b60405180910390a150505050565b611558604051806060016040528060258152602001613c89602591396121aa565b6037546001600160601b03908116908316111561159357604051632db8671b60e11b81526001600160601b0383166004820152602401610eba565b6001600160601b0382166115ba57604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151561010090910460ff161515036115ee57505050565b60028101546040805161010090920460ff161515825283151560208301526001600160601b038516917f9d2a9183b06e3492f91d3d88ae222e700c8873dd0068f9c3fc783eccb96a1ec4910160405180910390a260020180549115156101000261ff001990921691909117905550565b5f611680604051806060016040528060338152602001613cae603391396121aa565b61168c85858585612aa2565b90505b949350505050565b61169f6124a0565b6116a88161263e565b6033546040516001600160a01b038084169216907ffe7fd0d872def0f65050e9f38fc6691d0c192c694a56f09b04bec5fb2ea61f2b905f90a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5f610c6182612cbf565b60366020525f9081526040902080548190611727906137b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611753906137b3565b801561179e5780601f106117755761010080835404028352916020019161179e565b820191905f5260205f20905b81548152906001019060200180831161178157829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6117dc604051806060016040528060288152602001613ce1602891396121aa565b610f495f84846124ec565b6026545f906001600160a01b039081169083908116820361181a5760405162461bcd60e51b8152600401610eba9061373c565b6118226124a0565b61182b8461263e565b602680546001600160a01b038681166001600160a01b0319831681179093556040519116917f0f7eb572d1b3053a0a3a33c04151364cf88d163182a5e4e1088cb8e52321e08a91610f05918491613799565b6015545f906001600160a01b03908116908390811682036118b05760405162461bcd60e51b8152600401610eba9061373c565b6118b86124a0565b6118c18461263e565b601580546001600160a01b038681166001600160a01b03198316179092556040519116907fe1ddcb2dab8e5b03cfc8c67a0d5861d91d16f7bd2612fd381faf4541d212c9b290610f059083908890613799565b611935604051806060016040528060278152602001613d09602791396121aa565b6037546001600160601b03908116908416111561197057604051632db8671b60e11b81526001600160601b0384166004820152602401610eba565b5f61197b848461112d565b5f81815260096020526040902080549192509060ff166119ae57604051630665210960e21b815260040160405180910390fd5b82151581600601600c9054906101000a900460ff161515036119d1575050505050565b600681015460408051600160601b90920460ff161515825284151560208301526001600160a01b038616916001600160601b038816917fe40f9c4af130bdb5bd1650ab4bc918dba9d900fa94685f0113e72a6cfe6c5fcc910160405180910390a36006018054921515600160601b0260ff60601b1990931692909217909155505050565b611a936040518060400160405280601b81526020017f736574506f6f6c4c6162656c2875696e7439362c737472696e672900000000008152506121aa565b6037546001600160601b039081169084161115611ace57604051632db8671b60e11b81526001600160601b0384166004820152602401610eba565b6001600160601b038316611af557604051630203217b60e61b815260040160405180910390fd5b5f819003611b165760405163522e397360e11b815260040160405180910390fd5b6001600160601b0383165f90815260366020526040908190209051611b3e90849084906137eb565b60405190819003812090611b539083906137fa565b604051809103902003611b665750505050565b836001600160601b03167f1ebc260ee8077871ff0b70b184ff9dac4ecee8b0f7dcc4f3a3f5068549f5078e825f018585604051611ba593929190613894565b60405180910390a280610df983858361398b565b6025546001600160a01b0390811690829081168203611bea5760405162461bcd60e51b8152600401610eba9061373c565b611bf26124a0565b611bfb8361263e565b602580546001600160a01b038581166001600160a01b03198316179092556040519116907fa5ea5616d5f6dbbaa62fdfcf3856723216eed485c394d9e51ec8e6d40e1d1ac1906115299083908790613799565b6020545f90611c65906001600160a01b0316612d34565b670de0b6b3a76400008210611cae5760405162461bcd60e51b815260206004820152600f60248201526e70657263656e74203e3d203130302560881b6044820152606401610eba565b611cb78461263e565b611cc08361263e565b6020805460218054602280546001600160a01b03198086166001600160a01b038c8116919091179097558316898716179093558690556040519284169316917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e890611d2e9085908a90613799565b60405180910390a17f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac8287604051611d67929190613799565b60405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a15f5b979650505050505050565b611df36040518060400160405280601881526020017f736574466c6173684c6f616e50617573656428626f6f6c2900000000000000008152506121aa565b60395481151560ff909116151503611e085750565b6039546040805160ff9092161515825282151560208301527f79bcfb2700d56371c7684799f99d64cbcd91f1e360f8048a42c9ba534be7c0a8910160405180910390a16039805460ff1916911515919091179055565b6008602052815f5260405f208181548110611e77575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611ebc57611ebc613728565b815260208101919091526040015f205460ff169392505050565b6028545f906001600160a01b0390811690839081168203611f095760405162461bcd60e51b8152600401610eba9061373c565b611f116124a0565b611f1a8461263e565b602880546001600160a01b038681166001600160a01b03198316179092556040519116907f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd490610f059083908890613799565b5f611f76612d8f565b60185460ff16158015611f915750601854610100900460ff16155b611fcd5760405162461bcd60e51b815260206004820152600d60248201526c159052481a5cc81c185d5cd959609a1b6044820152606401610eba565b6015546001600160a01b03163314611ff257611feb600e6016612ddd565b9050610c61565b6001600160a01b0383165f908152601660205260408120839055610f49565b6039545f906001600160a01b036101009091048116908390811682036120495760405162461bcd60e51b8152600401610eba9061373c565b61206a604051806060016040528060228152602001613d30602291396121aa565b6120738461263e565b603980546001600160a01b03868116610100908102610100600160a81b03198416179093556040519290910416907fc4877d82ec0586c93fbd01eb65785e064f0c31b594e7f413e5f16502f25cf27390610f059083908890613799565b5f600554828082036120f45760405162461bcd60e51b8152600401610eba906136f1565b6120fc6124a0565b604080516020808201835286825282518082018452670c7d713b49da00008152835191820190935266b1a2bc2ec500008152815183519293921080612142575082518151115b1561215c57612152600580612ddd565b9550505050610f12565b600580549088905560408051828152602081018a90527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9910160405180910390a15f98975050505050505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906121dc9033908590600401613a45565b602060405180830381865afa1580156121f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061221b9190613a68565b6122575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610eba565b50565b5f60095f6122685f8561112d565b81526020019081526020015f209050919050565b805460ff166122575760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610eba565b6122e2604051806060016040528060298152602001613c60602991396121aa565b8151815181158015906122f457508082145b6123305760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610eba565b5f5b82811015610df95783818151811061234c5761234c613a83565b6020026020010151601f5f87848151811061236957612369613a83565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20819055508481815181106123a6576123a6613a83565b60200260200101516001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68583815181106123ea576123ea613a83565b602002602001015160405161240191815260200190565b60405180910390a2600101612332565b612432604051806060016040528060298152602001613b66602991396121aa565b825182515f5b82811015612498575f5b8281101561248f5761248787838151811061245f5761245f613a83565b602002602001015187838151811061247957612479613a83565b602002602001015187612e54565b600101612442565b50600101612438565b505050505050565b5f546001600160a01b031633146124ea5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610eba565b565b5f60095f6124fa868661112d565b81526020019081526020015f20600501548280820361252b5760405162461bcd60e51b8152600401610eba906136f1565b6037546001600160601b03908116908716111561256657604051632db8671b60e11b81526001600160601b0387166004820152602401610eba565b5f60095f612574898961112d565b81526020019081526020015f20905061258c8161227c565b670de0b6b3a76400008510156125d75760405162461bcd60e51b815260206004820152601060248201526f0d2dcc6cadce8d2ecca40784062ca62760831b6044820152606401610eba565b856001600160a01b0316876001600160601b03167fc1d7bc090f3a87255c2f4e56f66d1b7a49683d279f77921b1701aa5d733ef745836005015488604051612629929190918252602082015260400190565b60405180910390a3600581018590555f611daa565b6001600160a01b0381166122575760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610eba565b601c54158061269c5750601c5443105b156126a357565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156126ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127119190613a97565b9050805f0361271e575050565b5f8061272c43601c54612ef8565b90505f61273b601a5483612f31565b905080841061274c57809250612750565b8392505b601d54831015612761575050505050565b43601c55601b5461277f906001600160a01b03878116911685612f72565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156127fe575f80fd5b505af1158015612810573d5f803e3d5ffd5b505050505050505050565b61283c604051806060016040528060298152602001613be8602991396121aa565b81518151811580159061284e57508082145b61288a5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610eba565b5f5b82811015610df9578381815181106128a6576128a6613a83565b602002602001015160275f8784815181106128c3576128c3613a83565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208190555084818151811061290057612900613a83565b60200260200101516001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f885838151811061294457612944613a83565b602002602001015160405161295b91815260200190565b60405180910390a260010161288c565b61298c604051806060016040528060238152602001613c11602391396121aa565b6015546001600160a01b038381169116146129ad576129ad610ca98361225a565b6001600160a01b0382165f818152602d6020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b6004545f906001600160a01b0390811690839081168203612a3e5760405162461bcd60e51b8152600401610eba9061373c565b612a466124a0565b612a4f8461263e565b600480546001600160a01b038681166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e2290610f059083908890613799565b5f612aac8461263e565b6037546001600160601b039081169086161115612ae757604051632db8671b60e11b81526001600160601b0386166004820152602401610eba565b5f60095f612af5888861112d565b81526020019081526020015f209050612b0d8161227c565b670de0b6b3a7640000841115612b3157612b2960066008612ddd565b91505061168f565b8315801590612bab57506004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa158015612b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ba99190613a97565b155b15612bbc57612b29600d6009612ddd565b670de0b6b3a7640000831115612bd857612b2960146019612ddd565b83831015612bec57612b296014601a612ddd565b6001810154848114612c4f576001820185905560408051828152602081018790526001600160a01b038816916001600160601b038a16917f0d1a615379dc62cec7bc63b7e313a07ed659918f4ad3720b3af8041b305146f2910160405180910390a35b6004820154848114612cb2576004830185905560408051828152602081018790526001600160a01b038916916001600160601b038b16917fc90f7b48c299a8d58b0b9e2756e27773c6fb1daab159af052d6c5b791bc7eef7910160405180910390a35b5f98975050505050505050565b5f612cc86124a0565b612cd18261263e565b603180546001600160a01b038481166001600160a01b03198316179092556040519116907fcb20dab7409e4fb972d9adccb39530520b226ce6940d85c9523a499b950b6ea390612d249083908690613799565b60405180910390a15f9392505050565b5f546001600160a01b031633148061221b5750336001600160a01b038216146122575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610eba565b60185462010000900460ff16156124ea5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610eba565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836014811115612e1157612e11613728565b83601a811115612e2357612e23613728565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610f4957610f49613728565b612e60610ca98461225a565b6001600160a01b0383165f9081526029602052604081208291846008811115612e8b57612e8b613728565b815260208101919091526040015f20805460ff1916911515919091179055816008811115612ebb57612ebb613728565b836001600160a01b03167f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d83604051610d0e911515815260200190565b5f610f498383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612fc9565b5f610f4983836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612ff7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612fc4908490613050565b505050565b5f8184841115612fec5760405162461bcd60e51b8152600401610eba9190613aae565b50610f468385613ad4565b5f831580613003575082155b1561300f57505f610f49565b5f61301a8486613ae7565b9050836130278683613afe565b1483906130475760405162461bcd60e51b8152600401610eba9190613aae565b50949350505050565b5f6130a4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166131239092919063ffffffff16565b905080515f14806130c45750808060200190518101906130c49190613a68565b612fc45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610eba565b6060610f4684845f85855f80866001600160a01b031685876040516131489190613b1d565b5f6040518083038185875af1925050503d805f8114613182576040519150601f19603f3d011682016040523d82523d5f602084013e613187565b606091505b5091509150611daa87838387606083156132015782515f036131fa576001600160a01b0385163b6131fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610eba565b508161168f565b61168f83838151156132165781518083602001fd5b8060405162461bcd60e51b8152600401610eba9190613aae565b6001600160a01b0381168114612257575f80fd5b5f60208284031215613254575f80fd5b8135610f4981613230565b5f8060408385031215613270575f80fd5b823561327b81613230565b9150602083013561328b81613230565b809150509250929050565b5f602082840312156132a6575f80fd5b5035919050565b8015158114612257575f80fd5b5f805f606084860312156132cc575f80fd5b83356132d781613230565b925060208401356132e781613230565b915060408401356132f7816132ad565b809150509250925092565b5f8083601f840112613312575f80fd5b50813567ffffffffffffffff811115613329575f80fd5b6020830191508360208260051b8501011115613343575f80fd5b9250929050565b5f805f806040858703121561335d575f80fd5b843567ffffffffffffffff80821115613374575f80fd5b61338088838901613302565b90965094506020870135915080821115613398575f80fd5b506133a587828801613302565b95989497509550505050565b5f805f805f606086880312156133c5575f80fd5b853567ffffffffffffffff808211156133dc575f80fd5b6133e889838a01613302565b90975095506020880135915080821115613400575f80fd5b5061340d88828901613302565b9094509250506040860135613421816132ad565b809150509295509295909350565b5f6020828403121561343f575f80fd5b8135610f49816132ad565b80356001600160601b0381168114613460575f80fd5b919050565b5f805f60608486031215613477575f80fd5b6134808461344a565b9250602084013561349081613230565b929592945050506040919091013590565b5f80604083850312156134b2575f80fd5b82356134bd81613230565b9150602083013561328b816132ad565b5f80604083850312156134de575f80fd5b6134bd8361344a565b5f80604083850312156134f8575f80fd5b61327b8361344a565b5f805f60608486031215613513575f80fd5b833561351e81613230565b95602085013595506040909401359392505050565b5f805f8060808587031215613546575f80fd5b61354f8561344a565b9350602085013561355f81613230565b93969395505050506040820135916060013590565b5f60208284031215613584575f80fd5b610f498261344a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6135cd606083018661358d565b931515602083015250901515604090910152919050565b5f80604083850312156135f5575f80fd5b823561360081613230565b946020939093013593505050565b5f805f60608486031215613620575f80fd5b6132d78461344a565b5f805f6040848603121561363b575f80fd5b6136448461344a565b9250602084013567ffffffffffffffff80821115613660575f80fd5b818601915086601f830112613673575f80fd5b813581811115613681575f80fd5b876020828501011115613692575f80fd5b6020830194508093505050509250925092565b5f805f606084860312156136b7575f80fd5b833561348081613230565b5f80604083850312156136d3575f80fd5b82356136de81613230565b915060208301356009811061328b575f80fd5b6020808252601e908201527f6f6c642076616c75652069732073616d65206173206e65772076616c75650000604082015260600190565b634e487b7160e01b5f52602160045260245ffd5b60208082526022908201527f6f6c6420616464726573732069732073616d65206173206e6577206164647265604082015261737360f01b606082015260800190565b5f6020828403121561378e575f80fd5b8151610f4981613230565b6001600160a01b0392831681529116602082015260400190565b600181811c908216806137c757607f821691505b6020821081036137e557634e487b7160e01b5f52602260045260245ffd5b50919050565b818382375f9101908152919050565b5f808354613807816137b3565b6001828116801561381f576001811461383457613860565b60ff1984168752821515830287019450613860565b875f526020805f205f5b858110156138575781548a82015290840190820161383e565b50505082870194505b50929695505050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f8085546138a5816137b3565b806040860152606060018084165f81146138c657600181146138e257613911565b60ff1985166060890152606084151560051b8901019550613911565b8a5f526020805f205f5b868110156139075781548b82018701529084019082016138ec565b8a01606001975050505b5050505050828103602084015261392981858761386c565b9695505050505050565b634e487b7160e01b5f52604160045260245ffd5b601f821115612fc457805f5260205f20601f840160051c8101602085101561396c5750805b601f840160051c820191505b81811015610df9575f8155600101613978565b67ffffffffffffffff8311156139a3576139a3613933565b6139b7836139b183546137b3565b83613947565b5f601f8411600181146139e8575f85156139d15750838201355b5f19600387901b1c1916600186901b178355610df9565b5f83815260208120601f198716915b82811015613a1757868501358255602094850194600190920191016139f7565b5086821015613a33575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b03831681526040602082018190525f90610f469083018461358d565b5f60208284031215613a78575f80fd5b8151610f49816132ad565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215613aa7575f80fd5b5051919050565b602081525f610f49602083018461358d565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c6157610c61613ac0565b8082028115828204841417610c6157610c61613ac0565b5f82613b1857634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f92019182525091905056fe5f736574466f726365644c69717569646174696f6e466f725573657228616464726573732c616464726573732c626f6f6c295f736574416374696f6e7350617573656428616464726573735b5d2c75696e74385b5d2c626f6f6c297365744c69717569646174696f6e496e63656e746976652875696e7439362c616464726573732c75696e743235362973657457686974654c697374466c6173684c6f616e4163636f756e7428616464726573732c626f6f6c295f7365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d295f736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c29736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e74323536295f7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d29736574416c6c6f77436f7265506f6f6c46616c6c6261636b2875696e7439362c626f6f6c29736574436f6c6c61746572616c466163746f722875696e7439362c616464726573732c75696e743235362c75696e74323536297365744c69717569646174696f6e496e63656e7469766528616464726573732c75696e74323536297365744973426f72726f77416c6c6f7765642875696e7439362c616464726573732c626f6f6c29736574446576696174696f6e426f756e6465644f7261636c65286164647265737329a2646970667358221220b80c80afda590c889c163e200fc7f3834826fe74ca794e9d78a57820e66e46df64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106104d2575f3560e01c80638a7dc16511610284578063bf32442d11610161578063dce15449116100d5578063f445d7031161008f578063f445d70314610bd6578063f519fc3014610c03578063f851a44014610c16578063fa6331d814610c28578063fd51a3ad14610c31578063fe40768f14610c44575f80fd5b8063dce1544914610b3b578063dcfbc0c714610b4e578063e0f6123d14610b61578063e37d4b7914610b83578063e85a296014610bba578063e875544614610bcd575f80fd5b8063d136af4411610126578063d136af4414610740578063d24febad14610ae3578063d3270f9914610af6578063d463654c14610b09578063d6ad5c3914610b10578063d7c46d2d14610b23575f80fd5b8063bf32442d14610a7e578063c32094c7146108ff578063c5b4db5514610a8f578063c5f956af14610abd578063c7ee005e14610ad0575f80fd5b80639bf34cbb116101f8578063b8324c7c116101bd578063b8324c7c146109c2578063b88d846b14610a1d578063bb82aa5e14610a30578063bb85745014610a43578063bbb8864a14610a56578063bec04f7214610a75575f80fd5b80639bf34cbb146109635780639cfdd9e614610976578063a657e57914610989578063a89766dd1461099c578063b2eafc39146109af575f80fd5b80639254f5e5116102495780639254f5e5146108ec5780639460c8b5146108ff57806394b2294b1461091257806396c990641461091b5780639bb27d621461093d5780639bd8f6e814610950575f80fd5b80638a7dc165146108855780638b3113f6146107535780638c1ac18a146108a45780639159b177146108c6578063919a3736146108d9575f80fd5b80634964f48c116103b25780635dd3fc9d1161032657806373769099116102eb57806373769099146107ed578063765513831461082d5780637938146f1461083f5780637d172bd5146108525780637dc0d1d0146108655780637fb8e8cd14610878575f80fd5b80635dd3fc9d1461079f5780635f5af1aa146107be578063607ef6c1146105a95780636662c7c9146107d1578063719f701b146107e4575f80fd5b806351a485e41161037757806351a485e414610740578063522c656b1461075357806352d84d1e14610766578063530e784f1461077957806355ee1fe1146107795780635cc4fdeb1461078c575f80fd5b80634964f48c146106d55780634a584432146106e85780634d99c776146107075780634e0853db1461071a5780634ef233fc1461072d575f80fd5b80632678224711610449578063317b0b771161040e578063317b0b771461058157806335439240146106655780634088c73e1461067857806341a18d2c14610685578063425fad58146106af57806342adb211146106c2575f80fd5b8063267822471461060d5780632a6a6065146106205780632b5d790c146105fa5780632bc7e29e146106335780632ec0412414610652575f80fd5b806312348e961161049a57806312348e961461058157806317db216314610594578063186db48f146105a957806321af4569146105bc57806324a3d622146105e757806324aaa220146105fa575f80fd5b806302c3bcbb146104d657806304ef9d581461050857806308e0225c146105115780630db4b4e51461053b57806310b9833814610544575b5f80fd5b6104f56104e4366004613244565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6104f560225481565b6104f561051f36600461325f565b601360209081525f928352604080842090915290825290205481565b6104f5601d5481565b61057161055236600461325f565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016104ff565b6104f561058f366004613296565b610c57565b6105a76105a23660046132ba565b610c67565b005b6105a76105b736600461334a565b610d1b565b601e546105cf906001600160a01b031681565b6040516001600160a01b0390911681526020016104ff565b600a546105cf906001600160a01b031681565b6105a76106083660046133b1565b610d8c565b6001546105cf906001600160a01b031681565b61057161062e36600461342f565b610e00565b6104f5610641366004613244565b60166020525f908152604090205481565b6104f5610660366004613296565b610e96565b6104f5610673366004613465565b610f19565b6018546105719060ff1681565b6104f561069336600461325f565b601260209081525f928352604080842090915290825290205481565b6018546105719062010000900460ff1681565b6105a76106d03660046134a1565b610f50565b6105a76106e33660046134cd565b610ff8565b6104f56106f6366004613244565b601f6020525f908152604090205481565b6104f56107153660046134e7565b61112d565b6105a7610728366004613501565b61114a565b6105a761073b366004613244565b61120d565b6105a761074e36600461334a565b61133b565b6105a76107613660046134a1565b6113a6565b6105cf610774366004613296565b6113b4565b6104f5610787366004613244565b6113dc565b6104f561079a366004613501565b6113e6565b6104f56107ad366004613244565b602b6020525f908152604090205481565b6104f56107cc366004613244565b611414565b6105a76107df366004613296565b6114ab565b6104f5601c5481565b6108156107fb366004613244565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016104ff565b60185461057190610100900460ff1681565b6105a761084d3660046134cd565b611537565b601b546105cf906001600160a01b031681565b6004546105cf906001600160a01b031681565b6039546105719060ff1681565b6104f5610893366004613244565b60146020525f908152604090205481565b6105716108b2366004613244565b602d6020525f908152604090205460ff1681565b6104f56108d4366004613533565b61165e565b6105a76108e7366004613244565b611697565b6015546105cf906001600160a01b031681565b6104f561090d366004613244565b611703565b6104f560075481565b61092e610929366004613574565b61170d565b6040516104ff939291906135bb565b6025546105cf906001600160a01b031681565b6104f561095e3660046135e4565b6117ba565b6104f5610971366004613244565b6117e7565b6104f5610984366004613244565b61187d565b603754610815906001600160601b031681565b6105a76109aa36600461360e565b611914565b6020546105cf906001600160a01b031681565b6109f96109d0366004613244565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104ff565b6105a7610a2b366004613629565b611a55565b6002546105cf906001600160a01b031681565b6105a7610a51366004613244565b611bb9565b6104f5610a64366004613244565b602a6020525f908152604090205481565b6104f560175481565b6033546001600160a01b03166105cf565b610aa56ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b0390911681526020016104ff565b6021546105cf906001600160a01b031681565b6031546105cf906001600160a01b031681565b6104f5610af13660046136a5565b611c4e565b6026546105cf906001600160a01b031681565b6108155f81565b6105a7610b1e36600461342f565b611db5565b6039546105cf9061010090046001600160a01b031681565b6105cf610b493660046135e4565b611e5e565b6003546105cf906001600160a01b031681565b610571610b6f366004613244565b60386020525f908152604090205460ff1681565b6109f9610b91366004613244565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b610571610bc83660046136c2565b611e92565b6104f560055481565b610571610be436600461325f565b603260209081525f928352604080842090915290825290205460ff1681565b6104f5610c11366004613244565b611ed6565b5f546105cf906001600160a01b031681565b6104f5601a5481565b6104f5610c3f3660046135e4565b611f6d565b6104f5610c52366004613244565b612011565b5f610c61826120d0565b92915050565b610c88604051806060016040528060328152602001613b34603291396121aa565b6015546001600160a01b03838116911614610cae57610cae610ca98361225a565b61227c565b6001600160a01b038381165f81815260326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fc080966e9e93529edc1b244180c245bc60f3d86f1e690a17651a5e428746a8cd91015b60405180910390a3505050565b610d868484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f920191909152506122c192505050565b50505050565b610df98585808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284375f92019190915250869250612411915050565b5050505050565b5f610e3f6040518060400160405280601881526020017f5f73657450726f746f636f6c50617573656428626f6f6c2900000000000000008152506121aa565b60188054831515620100000262ff0000199091161790556040517fd7500633dd3ddd74daa7af62f8c8404c7fe4a81da179998db851696bed004b3890610e8a90841515815260200190565b60405180910390a15090565b5f60175482808203610ec35760405162461bcd60e51b8152600401610eba906136f1565b60405180910390fd5b610ecb6124a0565b601780549085905560408051828152602081018790527f73747d68b346dce1e932bcd238282e7ac84c01569e1f8d0469c222fdc6e9d5a491015b60405180910390a15f9350505b5050919050565b5f610f3b6040518060600160405280602f8152602001613b8f602f91396121aa565b610f468484846124ec565b90505b9392505050565b610f716040518060600160405280602a8152602001613bbe602a91396121aa565b610f7a8261263e565b6001600160a01b0382165f9081526038602052604090205481151560ff909116151503610fa5575050565b6001600160a01b0382165f81815260386020526040808220805460ff191685151590811790915590519092917f1f4df5032f431b9890646a781be28b0d693e581666d1a80be27ae3959069172291a35050565b6110366040518060400160405280601a81526020017f736574506f6f6c4163746976652875696e7439362c626f6f6c290000000000008152506121aa565b6037546001600160601b03908116908316111561107157604051632db8671b60e11b81526001600160601b0383166004820152602401610eba565b6001600160601b03821661109857604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151560ff9091161515036110c857505050565b60028101546040805160ff9092161515825283151560208301526001600160601b038516917f75e42fceb039532886a9d75717e843bfef67fd7f6f91f0fc5b1d48e9ce8a1ba9910160405180910390a2600201805460ff191691151591909117905550565b6001600160a01b031660a09190911b6001600160a01b0319161790565b601b546001600160a01b039081169084908116820361117b5760405162461bcd60e51b8152600401610eba9061373c565b6111836124a0565b61118c8561263e565b601b546001600160a01b0316156111a5576111a561268c565b601b80546001600160a01b0319166001600160a01b038716908117909155601c859055601d84905560408051868152602081018690527f7059037d74ee16b0fb06a4a30f3348dd2635f301f92e373c92899a25a522ef6e910160405180910390a25050505050565b6112156124a0565b61121e8161263e565b5f816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061127f919061377e565b6033549091506001600160a01b038083169116146112df5760405162461bcd60e51b815260206004820152601a60248201527f696e76616c6964207876732076746f6b656e20616464726573730000000000006044820152606401610eba565b6034546040516001600160a01b038085169216907f2565e1579c0926afb7113edbfd85373e85cadaa3e0346f04de19686a2bb86ed1905f90a350603480546001600160a01b0319166001600160a01b0392909216919091179055565b610d868484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f9201919091525061281b92505050565b6113b0828261296b565b5050565b600d81815481106113c3575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610c6182612a0b565b5f6114086040518060600160405280602c8152602001613c34602c91396121aa565b610f465f858585612aa2565b600a545f906001600160a01b03908116908390811682036114475760405162461bcd60e51b8152600401610eba9061373c565b61144f6124a0565b6114588461263e565b600a80546001600160a01b038681166001600160a01b03198316179092556040519116907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90610f059083908890613799565b601a54818082036114ce5760405162461bcd60e51b8152600401610eba906136f1565b6114d66124a0565b601b546001600160a01b0316156114ef576114ef61268c565b601a80549084905560408051828152602081018690527fe81d4ac15e5afa1e708e66664eddc697177423d950d133bda8262d8885e6da3b91015b60405180910390a150505050565b611558604051806060016040528060258152602001613c89602591396121aa565b6037546001600160601b03908116908316111561159357604051632db8671b60e11b81526001600160601b0383166004820152602401610eba565b6001600160601b0382166115ba57604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151561010090910460ff161515036115ee57505050565b60028101546040805161010090920460ff161515825283151560208301526001600160601b038516917f9d2a9183b06e3492f91d3d88ae222e700c8873dd0068f9c3fc783eccb96a1ec4910160405180910390a260020180549115156101000261ff001990921691909117905550565b5f611680604051806060016040528060338152602001613cae603391396121aa565b61168c85858585612aa2565b90505b949350505050565b61169f6124a0565b6116a88161263e565b6033546040516001600160a01b038084169216907ffe7fd0d872def0f65050e9f38fc6691d0c192c694a56f09b04bec5fb2ea61f2b905f90a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5f610c6182612cbf565b60366020525f9081526040902080548190611727906137b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611753906137b3565b801561179e5780601f106117755761010080835404028352916020019161179e565b820191905f5260205f20905b81548152906001019060200180831161178157829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6117dc604051806060016040528060288152602001613ce1602891396121aa565b610f495f84846124ec565b6026545f906001600160a01b039081169083908116820361181a5760405162461bcd60e51b8152600401610eba9061373c565b6118226124a0565b61182b8461263e565b602680546001600160a01b038681166001600160a01b0319831681179093556040519116917f0f7eb572d1b3053a0a3a33c04151364cf88d163182a5e4e1088cb8e52321e08a91610f05918491613799565b6015545f906001600160a01b03908116908390811682036118b05760405162461bcd60e51b8152600401610eba9061373c565b6118b86124a0565b6118c18461263e565b601580546001600160a01b038681166001600160a01b03198316179092556040519116907fe1ddcb2dab8e5b03cfc8c67a0d5861d91d16f7bd2612fd381faf4541d212c9b290610f059083908890613799565b611935604051806060016040528060278152602001613d09602791396121aa565b6037546001600160601b03908116908416111561197057604051632db8671b60e11b81526001600160601b0384166004820152602401610eba565b5f61197b848461112d565b5f81815260096020526040902080549192509060ff166119ae57604051630665210960e21b815260040160405180910390fd5b82151581600601600c9054906101000a900460ff161515036119d1575050505050565b600681015460408051600160601b90920460ff161515825284151560208301526001600160a01b038616916001600160601b038816917fe40f9c4af130bdb5bd1650ab4bc918dba9d900fa94685f0113e72a6cfe6c5fcc910160405180910390a36006018054921515600160601b0260ff60601b1990931692909217909155505050565b611a936040518060400160405280601b81526020017f736574506f6f6c4c6162656c2875696e7439362c737472696e672900000000008152506121aa565b6037546001600160601b039081169084161115611ace57604051632db8671b60e11b81526001600160601b0384166004820152602401610eba565b6001600160601b038316611af557604051630203217b60e61b815260040160405180910390fd5b5f819003611b165760405163522e397360e11b815260040160405180910390fd5b6001600160601b0383165f90815260366020526040908190209051611b3e90849084906137eb565b60405190819003812090611b539083906137fa565b604051809103902003611b665750505050565b836001600160601b03167f1ebc260ee8077871ff0b70b184ff9dac4ecee8b0f7dcc4f3a3f5068549f5078e825f018585604051611ba593929190613894565b60405180910390a280610df983858361398b565b6025546001600160a01b0390811690829081168203611bea5760405162461bcd60e51b8152600401610eba9061373c565b611bf26124a0565b611bfb8361263e565b602580546001600160a01b038581166001600160a01b03198316179092556040519116907fa5ea5616d5f6dbbaa62fdfcf3856723216eed485c394d9e51ec8e6d40e1d1ac1906115299083908790613799565b6020545f90611c65906001600160a01b0316612d34565b670de0b6b3a76400008210611cae5760405162461bcd60e51b815260206004820152600f60248201526e70657263656e74203e3d203130302560881b6044820152606401610eba565b611cb78461263e565b611cc08361263e565b6020805460218054602280546001600160a01b03198086166001600160a01b038c8116919091179097558316898716179093558690556040519284169316917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e890611d2e9085908a90613799565b60405180910390a17f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac8287604051611d67929190613799565b60405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a15f5b979650505050505050565b611df36040518060400160405280601881526020017f736574466c6173684c6f616e50617573656428626f6f6c2900000000000000008152506121aa565b60395481151560ff909116151503611e085750565b6039546040805160ff9092161515825282151560208301527f79bcfb2700d56371c7684799f99d64cbcd91f1e360f8048a42c9ba534be7c0a8910160405180910390a16039805460ff1916911515919091179055565b6008602052815f5260405f208181548110611e77575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611ebc57611ebc613728565b815260208101919091526040015f205460ff169392505050565b6028545f906001600160a01b0390811690839081168203611f095760405162461bcd60e51b8152600401610eba9061373c565b611f116124a0565b611f1a8461263e565b602880546001600160a01b038681166001600160a01b03198316179092556040519116907f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd490610f059083908890613799565b5f611f76612d8f565b60185460ff16158015611f915750601854610100900460ff16155b611fcd5760405162461bcd60e51b815260206004820152600d60248201526c159052481a5cc81c185d5cd959609a1b6044820152606401610eba565b6015546001600160a01b03163314611ff257611feb600e6016612ddd565b9050610c61565b6001600160a01b0383165f908152601660205260408120839055610f49565b6039545f906001600160a01b036101009091048116908390811682036120495760405162461bcd60e51b8152600401610eba9061373c565b61206a604051806060016040528060228152602001613d30602291396121aa565b6120738461263e565b603980546001600160a01b03868116610100908102610100600160a81b03198416179093556040519290910416907fc4877d82ec0586c93fbd01eb65785e064f0c31b594e7f413e5f16502f25cf27390610f059083908890613799565b5f600554828082036120f45760405162461bcd60e51b8152600401610eba906136f1565b6120fc6124a0565b604080516020808201835286825282518082018452670c7d713b49da00008152835191820190935266b1a2bc2ec500008152815183519293921080612142575082518151115b1561215c57612152600580612ddd565b9550505050610f12565b600580549088905560408051828152602081018a90527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9910160405180910390a15f98975050505050505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906121dc9033908590600401613a45565b602060405180830381865afa1580156121f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061221b9190613a68565b6122575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610eba565b50565b5f60095f6122685f8561112d565b81526020019081526020015f209050919050565b805460ff166122575760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610eba565b6122e2604051806060016040528060298152602001613c60602991396121aa565b8151815181158015906122f457508082145b6123305760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610eba565b5f5b82811015610df95783818151811061234c5761234c613a83565b6020026020010151601f5f87848151811061236957612369613a83565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20819055508481815181106123a6576123a6613a83565b60200260200101516001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68583815181106123ea576123ea613a83565b602002602001015160405161240191815260200190565b60405180910390a2600101612332565b612432604051806060016040528060298152602001613b66602991396121aa565b825182515f5b82811015612498575f5b8281101561248f5761248787838151811061245f5761245f613a83565b602002602001015187838151811061247957612479613a83565b602002602001015187612e54565b600101612442565b50600101612438565b505050505050565b5f546001600160a01b031633146124ea5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610eba565b565b5f60095f6124fa868661112d565b81526020019081526020015f20600501548280820361252b5760405162461bcd60e51b8152600401610eba906136f1565b6037546001600160601b03908116908716111561256657604051632db8671b60e11b81526001600160601b0387166004820152602401610eba565b5f60095f612574898961112d565b81526020019081526020015f20905061258c8161227c565b670de0b6b3a76400008510156125d75760405162461bcd60e51b815260206004820152601060248201526f0d2dcc6cadce8d2ecca40784062ca62760831b6044820152606401610eba565b856001600160a01b0316876001600160601b03167fc1d7bc090f3a87255c2f4e56f66d1b7a49683d279f77921b1701aa5d733ef745836005015488604051612629929190918252602082015260400190565b60405180910390a3600581018590555f611daa565b6001600160a01b0381166122575760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610eba565b601c54158061269c5750601c5443105b156126a357565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156126ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127119190613a97565b9050805f0361271e575050565b5f8061272c43601c54612ef8565b90505f61273b601a5483612f31565b905080841061274c57809250612750565b8392505b601d54831015612761575050505050565b43601c55601b5461277f906001600160a01b03878116911685612f72565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156127fe575f80fd5b505af1158015612810573d5f803e3d5ffd5b505050505050505050565b61283c604051806060016040528060298152602001613be8602991396121aa565b81518151811580159061284e57508082145b61288a5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610eba565b5f5b82811015610df9578381815181106128a6576128a6613a83565b602002602001015160275f8784815181106128c3576128c3613a83565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208190555084818151811061290057612900613a83565b60200260200101516001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f885838151811061294457612944613a83565b602002602001015160405161295b91815260200190565b60405180910390a260010161288c565b61298c604051806060016040528060238152602001613c11602391396121aa565b6015546001600160a01b038381169116146129ad576129ad610ca98361225a565b6001600160a01b0382165f818152602d6020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b6004545f906001600160a01b0390811690839081168203612a3e5760405162461bcd60e51b8152600401610eba9061373c565b612a466124a0565b612a4f8461263e565b600480546001600160a01b038681166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e2290610f059083908890613799565b5f612aac8461263e565b6037546001600160601b039081169086161115612ae757604051632db8671b60e11b81526001600160601b0386166004820152602401610eba565b5f60095f612af5888861112d565b81526020019081526020015f209050612b0d8161227c565b670de0b6b3a7640000841115612b3157612b2960066008612ddd565b91505061168f565b8315801590612bab57506004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa158015612b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ba99190613a97565b155b15612bbc57612b29600d6009612ddd565b670de0b6b3a7640000831115612bd857612b2960146019612ddd565b83831015612bec57612b296014601a612ddd565b6001810154848114612c4f576001820185905560408051828152602081018790526001600160a01b038816916001600160601b038a16917f0d1a615379dc62cec7bc63b7e313a07ed659918f4ad3720b3af8041b305146f2910160405180910390a35b6004820154848114612cb2576004830185905560408051828152602081018790526001600160a01b038916916001600160601b038b16917fc90f7b48c299a8d58b0b9e2756e27773c6fb1daab159af052d6c5b791bc7eef7910160405180910390a35b5f98975050505050505050565b5f612cc86124a0565b612cd18261263e565b603180546001600160a01b038481166001600160a01b03198316179092556040519116907fcb20dab7409e4fb972d9adccb39530520b226ce6940d85c9523a499b950b6ea390612d249083908690613799565b60405180910390a15f9392505050565b5f546001600160a01b031633148061221b5750336001600160a01b038216146122575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610eba565b60185462010000900460ff16156124ea5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610eba565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836014811115612e1157612e11613728565b83601a811115612e2357612e23613728565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610f4957610f49613728565b612e60610ca98461225a565b6001600160a01b0383165f9081526029602052604081208291846008811115612e8b57612e8b613728565b815260208101919091526040015f20805460ff1916911515919091179055816008811115612ebb57612ebb613728565b836001600160a01b03167f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d83604051610d0e911515815260200190565b5f610f498383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612fc9565b5f610f4983836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612ff7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612fc4908490613050565b505050565b5f8184841115612fec5760405162461bcd60e51b8152600401610eba9190613aae565b50610f468385613ad4565b5f831580613003575082155b1561300f57505f610f49565b5f61301a8486613ae7565b9050836130278683613afe565b1483906130475760405162461bcd60e51b8152600401610eba9190613aae565b50949350505050565b5f6130a4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166131239092919063ffffffff16565b905080515f14806130c45750808060200190518101906130c49190613a68565b612fc45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610eba565b6060610f4684845f85855f80866001600160a01b031685876040516131489190613b1d565b5f6040518083038185875af1925050503d805f8114613182576040519150601f19603f3d011682016040523d82523d5f602084013e613187565b606091505b5091509150611daa87838387606083156132015782515f036131fa576001600160a01b0385163b6131fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610eba565b508161168f565b61168f83838151156132165781518083602001fd5b8060405162461bcd60e51b8152600401610eba9190613aae565b6001600160a01b0381168114612257575f80fd5b5f60208284031215613254575f80fd5b8135610f4981613230565b5f8060408385031215613270575f80fd5b823561327b81613230565b9150602083013561328b81613230565b809150509250929050565b5f602082840312156132a6575f80fd5b5035919050565b8015158114612257575f80fd5b5f805f606084860312156132cc575f80fd5b83356132d781613230565b925060208401356132e781613230565b915060408401356132f7816132ad565b809150509250925092565b5f8083601f840112613312575f80fd5b50813567ffffffffffffffff811115613329575f80fd5b6020830191508360208260051b8501011115613343575f80fd5b9250929050565b5f805f806040858703121561335d575f80fd5b843567ffffffffffffffff80821115613374575f80fd5b61338088838901613302565b90965094506020870135915080821115613398575f80fd5b506133a587828801613302565b95989497509550505050565b5f805f805f606086880312156133c5575f80fd5b853567ffffffffffffffff808211156133dc575f80fd5b6133e889838a01613302565b90975095506020880135915080821115613400575f80fd5b5061340d88828901613302565b9094509250506040860135613421816132ad565b809150509295509295909350565b5f6020828403121561343f575f80fd5b8135610f49816132ad565b80356001600160601b0381168114613460575f80fd5b919050565b5f805f60608486031215613477575f80fd5b6134808461344a565b9250602084013561349081613230565b929592945050506040919091013590565b5f80604083850312156134b2575f80fd5b82356134bd81613230565b9150602083013561328b816132ad565b5f80604083850312156134de575f80fd5b6134bd8361344a565b5f80604083850312156134f8575f80fd5b61327b8361344a565b5f805f60608486031215613513575f80fd5b833561351e81613230565b95602085013595506040909401359392505050565b5f805f8060808587031215613546575f80fd5b61354f8561344a565b9350602085013561355f81613230565b93969395505050506040820135916060013590565b5f60208284031215613584575f80fd5b610f498261344a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6135cd606083018661358d565b931515602083015250901515604090910152919050565b5f80604083850312156135f5575f80fd5b823561360081613230565b946020939093013593505050565b5f805f60608486031215613620575f80fd5b6132d78461344a565b5f805f6040848603121561363b575f80fd5b6136448461344a565b9250602084013567ffffffffffffffff80821115613660575f80fd5b818601915086601f830112613673575f80fd5b813581811115613681575f80fd5b876020828501011115613692575f80fd5b6020830194508093505050509250925092565b5f805f606084860312156136b7575f80fd5b833561348081613230565b5f80604083850312156136d3575f80fd5b82356136de81613230565b915060208301356009811061328b575f80fd5b6020808252601e908201527f6f6c642076616c75652069732073616d65206173206e65772076616c75650000604082015260600190565b634e487b7160e01b5f52602160045260245ffd5b60208082526022908201527f6f6c6420616464726573732069732073616d65206173206e6577206164647265604082015261737360f01b606082015260800190565b5f6020828403121561378e575f80fd5b8151610f4981613230565b6001600160a01b0392831681529116602082015260400190565b600181811c908216806137c757607f821691505b6020821081036137e557634e487b7160e01b5f52602260045260245ffd5b50919050565b818382375f9101908152919050565b5f808354613807816137b3565b6001828116801561381f576001811461383457613860565b60ff1984168752821515830287019450613860565b875f526020805f205f5b858110156138575781548a82015290840190820161383e565b50505082870194505b50929695505050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f8085546138a5816137b3565b806040860152606060018084165f81146138c657600181146138e257613911565b60ff1985166060890152606084151560051b8901019550613911565b8a5f526020805f205f5b868110156139075781548b82018701529084019082016138ec565b8a01606001975050505b5050505050828103602084015261392981858761386c565b9695505050505050565b634e487b7160e01b5f52604160045260245ffd5b601f821115612fc457805f5260205f20601f840160051c8101602085101561396c5750805b601f840160051c820191505b81811015610df9575f8155600101613978565b67ffffffffffffffff8311156139a3576139a3613933565b6139b7836139b183546137b3565b83613947565b5f601f8411600181146139e8575f85156139d15750838201355b5f19600387901b1c1916600186901b178355610df9565b5f83815260208120601f198716915b82811015613a1757868501358255602094850194600190920191016139f7565b5086821015613a33575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b03831681526040602082018190525f90610f469083018461358d565b5f60208284031215613a78575f80fd5b8151610f49816132ad565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215613aa7575f80fd5b5051919050565b602081525f610f49602083018461358d565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c6157610c61613ac0565b8082028115828204841417610c6157610c61613ac0565b5f82613b1857634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f92019182525091905056fe5f736574466f726365644c69717569646174696f6e466f725573657228616464726573732c616464726573732c626f6f6c295f736574416374696f6e7350617573656428616464726573735b5d2c75696e74385b5d2c626f6f6c297365744c69717569646174696f6e496e63656e746976652875696e7439362c616464726573732c75696e743235362973657457686974654c697374466c6173684c6f616e4163636f756e7428616464726573732c626f6f6c295f7365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d295f736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c29736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e74323536295f7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d29736574416c6c6f77436f7265506f6f6c46616c6c6261636b2875696e7439362c626f6f6c29736574436f6c6c61746572616c466163746f722875696e7439362c616464726573732c75696e743235362c75696e74323536297365744c69717569646174696f6e496e63656e7469766528616464726573732c75696e74323536297365744973426f72726f77416c6c6f7765642875696e7439362c616464726573732c626f6f6c29736574446576696174696f6e426f756e6465644f7261636c65286164647265737329a2646970667358221220b80c80afda590c889c163e200fc7f3834826fe74ca794e9d78a57820e66e46df64736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This facet contains all the setters for the states", @@ -2757,6 +2808,14 @@ "_0": "uint256 0=success, otherwise a failure. (See ErrorReporter for details)" } }, + "setDeviationBoundedOracle(address)": { + "params": { + "newDeviationBoundedOracle": "The new DeviationBoundedOracle contract" + }, + "returns": { + "_0": "uint256 0=success, otherwise a failure" + } + }, "setFlashLoanPaused(bool)": { "custom:access": "Only Governance", "custom:event": "Emits FlashLoanPauseChanged event", @@ -2998,6 +3057,9 @@ "NewComptrollerLens(address,address)": { "notice": "Emitted when ComptrollerLens address is changed" }, + "NewDeviationBoundedOracle(address,address)": { + "notice": "Emitted when deviation bounded oracle is changed" + }, "NewLiquidationIncentive(uint96,address,uint256,uint256)": { "notice": "Emitted when liquidation incentive for a market in a pool is changed by admin" }, @@ -3145,6 +3207,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "flashLoanPaused()": { "notice": "Whether flash loans are paused system-wide" }, @@ -3208,6 +3273,9 @@ "setCollateralFactor(uint96,address,uint256,uint256)": { "notice": "Sets the collateral factor and liquidation threshold for a market in the specified pool." }, + "setDeviationBoundedOracle(address)": { + "notice": "Sets the DeviationBoundedOracle for conservative CF-path pricing" + }, "setFlashLoanPaused(bool)": { "notice": "Pause or unpause flash loans system-wide" }, @@ -3302,7 +3370,7 @@ "storageLayout": { "storage": [ { - "astId": 1677, + "astId": 9226, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "admin", "offset": 0, @@ -3310,7 +3378,7 @@ "type": "t_address" }, { - "astId": 1680, + "astId": 9229, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "pendingAdmin", "offset": 0, @@ -3318,7 +3386,7 @@ "type": "t_address" }, { - "astId": 1683, + "astId": 9232, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "comptrollerImplementation", "offset": 0, @@ -3326,7 +3394,7 @@ "type": "t_address" }, { - "astId": 1686, + "astId": 9235, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -3334,15 +3402,15 @@ "type": "t_address" }, { - "astId": 1693, + "astId": 9242, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)992" + "type": "t_contract(ResilientOracleInterface)7913" }, { - "astId": 1696, + "astId": 9245, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "closeFactorMantissa", "offset": 0, @@ -3350,7 +3418,7 @@ "type": "t_uint256" }, { - "astId": 1699, + "astId": 9248, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -3358,7 +3426,7 @@ "type": "t_uint256" }, { - "astId": 1702, + "astId": 9251, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "maxAssets", "offset": 0, @@ -3366,23 +3434,23 @@ "type": "t_uint256" }, { - "astId": 1709, + "astId": 9258, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)" }, { - "astId": 1743, + "astId": 9292, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)" }, { - "astId": 1746, + "astId": 9295, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "pauseGuardian", "offset": 0, @@ -3390,7 +3458,7 @@ "type": "t_address" }, { - "astId": 1749, + "astId": 9298, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -3398,7 +3466,7 @@ "type": "t_bool" }, { - "astId": 1752, + "astId": 9301, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -3406,7 +3474,7 @@ "type": "t_bool" }, { - "astId": 1755, + "astId": 9304, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "transferGuardianPaused", "offset": 22, @@ -3414,7 +3482,7 @@ "type": "t_bool" }, { - "astId": 1758, + "astId": 9307, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -3422,7 +3490,7 @@ "type": "t_bool" }, { - "astId": 1763, + "astId": 9312, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "mintGuardianPaused", "offset": 0, @@ -3430,7 +3498,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1768, + "astId": 9317, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -3438,15 +3506,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1780, + "astId": 9329, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)32634)dyn_storage" + "type": "t_array(t_contract(VToken)49461)dyn_storage" }, { - "astId": 1783, + "astId": 9332, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusRate", "offset": 0, @@ -3454,7 +3522,7 @@ "type": "t_uint256" }, { - "astId": 1788, + "astId": 9337, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusSpeeds", "offset": 0, @@ -3462,23 +3530,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1794, + "astId": 9343, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1800, + "astId": 9349, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1807, + "astId": 9356, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusSupplierIndex", "offset": 0, @@ -3486,7 +3554,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1814, + "astId": 9363, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -3494,7 +3562,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1819, + "astId": 9368, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusAccrued", "offset": 0, @@ -3502,15 +3570,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1823, + "astId": 9372, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)25733" + "type": "t_contract(VAIControllerInterface)42511" }, { - "astId": 1828, + "astId": 9377, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "mintedVAIs", "offset": 0, @@ -3518,7 +3586,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1831, + "astId": 9380, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "vaiMintRate", "offset": 0, @@ -3526,7 +3594,7 @@ "type": "t_uint256" }, { - "astId": 1834, + "astId": 9383, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -3534,7 +3602,7 @@ "type": "t_bool" }, { - "astId": 1836, + "astId": 9385, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -3542,7 +3610,7 @@ "type": "t_bool" }, { - "astId": 1839, + "astId": 9388, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "protocolPaused", "offset": 2, @@ -3550,7 +3618,7 @@ "type": "t_bool" }, { - "astId": 1842, + "astId": 9391, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusVAIRate", "offset": 0, @@ -3558,7 +3626,7 @@ "type": "t_uint256" }, { - "astId": 1848, + "astId": 9397, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -3566,7 +3634,7 @@ "type": "t_uint256" }, { - "astId": 1850, + "astId": 9399, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "vaiVaultAddress", "offset": 0, @@ -3574,7 +3642,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9401, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "releaseStartBlock", "offset": 0, @@ -3582,7 +3650,7 @@ "type": "t_uint256" }, { - "astId": 1854, + "astId": 9403, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "minReleaseAmount", "offset": 0, @@ -3590,7 +3658,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9409, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "borrowCapGuardian", "offset": 0, @@ -3598,7 +3666,7 @@ "type": "t_address" }, { - "astId": 1865, + "astId": 9414, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "borrowCaps", "offset": 0, @@ -3606,7 +3674,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1871, + "astId": 9420, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "treasuryGuardian", "offset": 0, @@ -3614,7 +3682,7 @@ "type": "t_address" }, { - "astId": 1874, + "astId": 9423, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "treasuryAddress", "offset": 0, @@ -3622,7 +3690,7 @@ "type": "t_address" }, { - "astId": 1877, + "astId": 9426, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "treasuryPercent", "offset": 0, @@ -3630,7 +3698,7 @@ "type": "t_uint256" }, { - "astId": 1885, + "astId": 9434, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -3638,7 +3706,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9439, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "lastContributorBlock", "offset": 0, @@ -3646,7 +3714,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1895, + "astId": 9444, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "liquidatorContract", "offset": 0, @@ -3654,15 +3722,15 @@ "type": "t_address" }, { - "astId": 1901, + "astId": 9450, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1660" + "type": "t_contract(ComptrollerLensInterface)9207" }, { - "astId": 1909, + "astId": 9458, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "supplyCaps", "offset": 0, @@ -3670,7 +3738,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1915, + "astId": 9464, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "accessControl", "offset": 0, @@ -3678,7 +3746,7 @@ "type": "t_address" }, { - "astId": 1922, + "astId": 9471, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_actionPaused", "offset": 0, @@ -3686,7 +3754,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1930, + "astId": 9479, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -3694,7 +3762,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1935, + "astId": 9484, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -3702,7 +3770,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1945, + "astId": 9494, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "approvedDelegates", "offset": 0, @@ -3710,7 +3778,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1953, + "astId": 9502, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -3718,23 +3786,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1972, + "astId": 9521, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)" }, { - "astId": 1977, + "astId": 9526, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)" }, { - "astId": 1980, + "astId": 9529, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_facetAddresses", "offset": 0, @@ -3742,15 +3810,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1987, + "astId": 9536, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)22911" + "type": "t_contract(IPrime)33730" }, { - "astId": 1997, + "astId": 9546, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -3758,7 +3826,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 2003, + "astId": 9552, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "xvs", "offset": 0, @@ -3766,7 +3834,7 @@ "type": "t_address" }, { - "astId": 2006, + "astId": 9555, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "xvsVToken", "offset": 0, @@ -3774,7 +3842,7 @@ "type": "t_address" }, { - "astId": 2028, + "astId": 9577, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "userPoolId", "offset": 0, @@ -3782,15 +3850,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2034, + "astId": 9583, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)2023_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)9572_storage)" }, { - "astId": 2037, + "astId": 9586, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "lastPoolId", "offset": 0, @@ -3798,7 +3866,7 @@ "type": "t_uint96" }, { - "astId": 2045, + "astId": 9594, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -3806,12 +3874,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2048, + "astId": 9597, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 9604, + "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)7883" } ], "types": { @@ -3832,8 +3908,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)32634)dyn_storage": { - "base": "t_contract(VToken)32634", + "t_array(t_contract(VToken)49461)dyn_storage": { + "base": "t_contract(VToken)49461", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -3848,37 +3924,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1660": { + "t_contract(ComptrollerLensInterface)9207": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)22911": { + "t_contract(IDeviationBoundedOracle)7883": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)33730": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)992": { + "t_contract(ResilientOracleInterface)7913": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)25733": { + "t_contract(VAIControllerInterface)42511": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)32634": { + "t_contract(VToken)49461": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)32634)dyn_storage" + "value": "t_array(t_contract(VToken)49461)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -3908,19 +3989,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1967_storage" + "value": "t_struct(FacetFunctionSelectors)9516_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1775_storage" + "value": "t_struct(VenusMarketState)9324_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -3936,12 +4017,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1961_storage" + "value": "t_struct(FacetAddressAndPosition)9510_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -3950,31 +4031,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)2023_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)9572_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)2023_storage" + "value": "t_struct(PoolData)9572_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11427", + "key": "t_userDefinedValueType(PoolMarketId)19217", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1736_storage" + "value": "t_struct(Market)9285_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1961_storage": { + "t_struct(FacetAddressAndPosition)9510_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1958, + "astId": 9507, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "facetAddress", "offset": 0, @@ -3982,7 +4063,7 @@ "type": "t_address" }, { - "astId": 1960, + "astId": 9509, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "functionSelectorPosition", "offset": 20, @@ -3992,12 +4073,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1967_storage": { + "t_struct(FacetFunctionSelectors)9516_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1964, + "astId": 9513, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "functionSelectors", "offset": 0, @@ -4005,7 +4086,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1966, + "astId": 9515, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "facetAddressPosition", "offset": 0, @@ -4015,12 +4096,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1736_storage": { + "t_struct(Market)9285_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1712, + "astId": 9261, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isListed", "offset": 0, @@ -4028,7 +4109,7 @@ "type": "t_bool" }, { - "astId": 1715, + "astId": 9264, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -4036,7 +4117,7 @@ "type": "t_uint256" }, { - "astId": 1720, + "astId": 9269, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "accountMembership", "offset": 0, @@ -4044,7 +4125,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1723, + "astId": 9272, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isVenus", "offset": 0, @@ -4052,7 +4133,7 @@ "type": "t_bool" }, { - "astId": 1726, + "astId": 9275, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -4060,7 +4141,7 @@ "type": "t_uint256" }, { - "astId": 1729, + "astId": 9278, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -4068,7 +4149,7 @@ "type": "t_uint256" }, { - "astId": 1732, + "astId": 9281, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "poolId", "offset": 0, @@ -4076,7 +4157,7 @@ "type": "t_uint96" }, { - "astId": 1735, + "astId": 9284, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isBorrowAllowed", "offset": 12, @@ -4086,12 +4167,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)2023_storage": { + "t_struct(PoolData)9572_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 2012, + "astId": 9561, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "label", "offset": 0, @@ -4099,7 +4180,7 @@ "type": "t_string_storage" }, { - "astId": 2016, + "astId": 9565, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "vTokens", "offset": 0, @@ -4107,7 +4188,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 2019, + "astId": 9568, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isActive", "offset": 0, @@ -4115,7 +4196,7 @@ "type": "t_bool" }, { - "astId": 2022, + "astId": 9571, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -4125,12 +4206,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1775_storage": { + "t_struct(VenusMarketState)9324_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1771, + "astId": 9320, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "index", "offset": 0, @@ -4138,7 +4219,7 @@ "type": "t_uint224" }, { - "astId": 1774, + "astId": 9323, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "block", "offset": 28, @@ -4168,7 +4249,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11427": { + "t_userDefinedValueType(PoolMarketId)19217": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bscmainnet/Unitroller_Implementation.json b/deployments/bscmainnet/Unitroller_Implementation.json index c25c4b511..16d69f202 100644 --- a/deployments/bscmainnet/Unitroller_Implementation.json +++ b/deployments/bscmainnet/Unitroller_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0xB2243Da976F2cbAAa4dd1a76BF7F6EFbe22c4CFc", + "address": "0x82cA18785BBbacBeD1C4f482921E2B2E989D8C08", "abi": [ { "anonymous": false, @@ -218,6 +218,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -911,28 +924,28 @@ "type": "function" } ], - "transactionHash": "0xa043c2d54ccae738d087d3a7b2d27b24fee0e5bba15bfd4a2b40b3a63c011cb8", + "transactionHash": "0xa618d67d107bf5ac063aaa4e3aae2ac6999456d4c37008f13695f9caa4a937fe", "receipt": { "to": null, - "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0xB2243Da976F2cbAAa4dd1a76BF7F6EFbe22c4CFc", - "transactionIndex": 176, - "gasUsed": "1827052", + "from": "0x9b0A3EAE7f174937d31745B710BbeA68e9D1BEf7", + "contractAddress": "0x82cA18785BBbacBeD1C4f482921E2B2E989D8C08", + "transactionIndex": 36, + "gasUsed": "1837813", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4c2d842235e720e3ce68c2140ff4a83ac53478d4eacfa440a0f751898ed9f530", - "transactionHash": "0xa043c2d54ccae738d087d3a7b2d27b24fee0e5bba15bfd4a2b40b3a63c011cb8", + "blockHash": "0xd2d91dc6d32635153cc9790c9554c5e520569a542d5d8a0c32c77d83be648acc", + "transactionHash": "0xa618d67d107bf5ac063aaa4e3aae2ac6999456d4c37008f13695f9caa4a937fe", "logs": [], - "blockNumber": 66293515, - "cumulativeGasUsed": "28592821", + "blockNumber": 95559322, + "cumulativeGasUsed": "7146506", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 4, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"indexed\":false,\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"}],\"name\":\"DiamondCut\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"diamondCut_\",\"type\":\"tuple[]\"}],\"name\":\"diamondCut\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"functionSelector\",\"type\":\"bytes4\"}],\"name\":\"facetAddress\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"functionSelectorPosition\",\"type\":\"uint96\"}],\"internalType\":\"struct ComptrollerV13Storage.FacetAddressAndPosition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facetAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"facet\",\"type\":\"address\"}],\"name\":\"facetFunctionSelectors\",\"outputs\":[{\"internalType\":\"bytes4[]\",\"name\":\"\",\"type\":\"bytes4[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"facet\",\"type\":\"address\"}],\"name\":\"facetPosition\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facets\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct Diamond.Facet[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"_become(address)\":{\"params\":{\"unitroller\":\"Address of the unitroller\"}},\"diamondCut((address,uint8,bytes4[])[])\":{\"details\":\"Allows the contract admin to add function selectors\",\"params\":{\"diamondCut_\":\"IDiamondCut contains facets address, action and function selectors\"}},\"facetAddress(bytes4)\":{\"params\":{\"functionSelector\":\"function selector\"},\"returns\":{\"_0\":\"FacetAddressAndPosition facet address and position\"}},\"facetAddresses()\":{\"returns\":{\"_0\":\"facetAddresses Array of facet addresses\"}},\"facetFunctionSelectors(address)\":{\"params\":{\"facet\":\"Address of the facet\"},\"returns\":{\"_0\":\"selectors Array of function selectors\"}},\"facetPosition(address)\":{\"params\":{\"facet\":\"Address of the facet\"},\"returns\":{\"_0\":\"Position of the facet\"}},\"facets()\":{\"returns\":{\"_0\":\"facets_ Array of Facet\"}}},\"title\":\"Diamond\",\"version\":1},\"userdoc\":{\"events\":{\"DiamondCut((address,uint8,bytes4[])[])\":{\"notice\":\"Emitted when functions are added, replaced or removed to facets\"}},\"kind\":\"user\",\"methods\":{\"_become(address)\":{\"notice\":\"Call _acceptImplementation to accept the diamond proxy as new implementaion\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"diamondCut((address,uint8,bytes4[])[])\":{\"notice\":\"To add function selectors to the facet's mapping\"},\"facetAddress(bytes4)\":{\"notice\":\"Get facet address and position through function selector\"},\"facetAddresses()\":{\"notice\":\"Get all facet addresses\"},\"facetFunctionSelectors(address)\":{\"notice\":\"Get all function selectors mapped to the facet address\"},\"facetPosition(address)\":{\"notice\":\"Get facet position in the _facetFunctionSelectors through facet address\"},\"facets()\":{\"notice\":\"Get all facets address and their function selector\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This contract contains functions related to facets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/Diamond.sol\":\"Diamond\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/Diamond.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IDiamondCut } from \\\"./interfaces/IDiamondCut.sol\\\";\\nimport { Unitroller } from \\\"../Unitroller.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../ComptrollerStorage.sol\\\";\\n\\n/**\\n * @title Diamond\\n * @author Venus\\n * @notice This contract contains functions related to facets\\n */\\ncontract Diamond is IDiamondCut, ComptrollerV18Storage {\\n /// @notice Emitted when functions are added, replaced or removed to facets\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut);\\n\\n struct Facet {\\n address facetAddress;\\n bytes4[] functionSelectors;\\n }\\n\\n /**\\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\\n * @param unitroller Address of the unitroller\\n */\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"not authorized\\\");\\n }\\n\\n /**\\n * @notice To add function selectors to the facet's mapping\\n * @dev Allows the contract admin to add function selectors\\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\\n */\\n function diamondCut(IDiamondCut.FacetCut[] memory diamondCut_) public {\\n require(msg.sender == admin, \\\"only unitroller admin can\\\");\\n libDiamondCut(diamondCut_);\\n }\\n\\n /**\\n * @notice Get all function selectors mapped to the facet address\\n * @param facet Address of the facet\\n * @return selectors Array of function selectors\\n */\\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\\n return _facetFunctionSelectors[facet].functionSelectors;\\n }\\n\\n /**\\n * @notice Get facet position in the _facetFunctionSelectors through facet address\\n * @param facet Address of the facet\\n * @return Position of the facet\\n */\\n function facetPosition(address facet) external view returns (uint256) {\\n return _facetFunctionSelectors[facet].facetAddressPosition;\\n }\\n\\n /**\\n * @notice Get all facet addresses\\n * @return facetAddresses Array of facet addresses\\n */\\n function facetAddresses() external view returns (address[] memory) {\\n return _facetAddresses;\\n }\\n\\n /**\\n * @notice Get facet address and position through function selector\\n * @param functionSelector function selector\\n * @return FacetAddressAndPosition facet address and position\\n */\\n function facetAddress(\\n bytes4 functionSelector\\n ) external view returns (ComptrollerV18Storage.FacetAddressAndPosition memory) {\\n return _selectorToFacetAndPosition[functionSelector];\\n }\\n\\n /**\\n * @notice Get all facets address and their function selector\\n * @return facets_ Array of Facet\\n */\\n function facets() external view returns (Facet[] memory) {\\n uint256 facetsLength = _facetAddresses.length;\\n Facet[] memory facets_ = new Facet[](facetsLength);\\n for (uint256 i; i < facetsLength; ++i) {\\n address facet = _facetAddresses[i];\\n facets_[i].facetAddress = facet;\\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\\n }\\n return facets_;\\n }\\n\\n /**\\n * @notice To add function selectors to the facets' mapping\\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\\n */\\n function libDiamondCut(IDiamondCut.FacetCut[] memory diamondCut_) internal {\\n uint256 diamondCutLength = diamondCut_.length;\\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\\n IDiamondCut.FacetCutAction action = diamondCut_[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(diamondCut_);\\n }\\n\\n /**\\n * @notice Add function selectors to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to add in the mapping\\n */\\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n require(functionSelectors.length != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n require(facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(facetAddress);\\n }\\n uint256 functionSelectorsLength = functionSelectors.length;\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(selector, selectorPosition, facetAddress);\\n ++selectorPosition;\\n }\\n }\\n\\n /**\\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to replace in the mapping\\n */\\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n require(functionSelectors.length != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n require(facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(facetAddress);\\n }\\n uint256 functionSelectorsLength = functionSelectors.length;\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(oldFacetAddress, selector);\\n addFunction(selector, selectorPosition, facetAddress);\\n ++selectorPosition;\\n }\\n }\\n\\n /**\\n * @notice Remove function selectors to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to remove in the mapping\\n */\\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n uint256 functionSelectorsLength = functionSelectors.length;\\n require(functionSelectorsLength != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n // if function does not exist then do nothing and revert\\n require(facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(oldFacetAddress, selector);\\n }\\n }\\n\\n /**\\n * @notice Add new facet to the proxy\\n * @param facetAddress Address of the facet\\n */\\n function addFacet(address facetAddress) internal {\\n enforceHasContractCode(facetAddress, \\\"Diamond: New facet has no code\\\");\\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\\n _facetAddresses.push(facetAddress);\\n }\\n\\n /**\\n * @notice Add function selector to the facet's address mapping\\n * @param selector funciton selector need to be added\\n * @param selectorPosition funciton selector position\\n * @param facetAddress Address of the facet\\n */\\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\\n }\\n\\n /**\\n * @notice Remove function selector to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param selector function selectors need to remove in the mapping\\n */\\n function removeFunction(address facetAddress, bytes4 selector) internal {\\n require(facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\\n // if not the same then replace selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\\n delete _selectorToFacetAndPosition[selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n _facetAddresses.pop();\\n delete _facetFunctionSelectors[facetAddress];\\n }\\n }\\n\\n /**\\n * @dev Ensure that the given address has contract code deployed\\n * @param _contract The address to check for contract code\\n * @param _errorMessage The error message to display if the contract code is not deployed\\n */\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize != 0, _errorMessage);\\n }\\n\\n // Find facet for function that is called and execute the\\n // function if a facet is found and return any value.\\n fallback() external {\\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\\n require(facet != address(0), \\\"Diamond: Function does not exist\\\");\\n // Execute public function from facet using delegatecall and return any value.\\n assembly {\\n // copy function selector and any arguments\\n calldatacopy(0, 0, calldatasize())\\n // execute function call using the facet\\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\\n // get any return value\\n returndatacopy(0, 0, returndatasize())\\n // return any return value or error back to the caller\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x095890007d044e6b2cd9a61f96c64508f3ff5de9227147402a28de084eafe72b\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n function diamondCut(FacetCut[] calldata _diamondCut) external;\\n}\\n\",\"keccak256\":\"0xcb93543c9122cf328715d2b242e99f8ca234bd1347d82290ad7a4e028f358141\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Unitroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { UnitrollerAdminStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../Utils/ErrorReporter.sol\\\";\\n\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * VTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n fallback() external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize())\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize())\\n }\\n default {\\n return(free_mem_ptr, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7e552ae197db0095044af62614b09426d3570bf15593aa7703be3a517287074b\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b5061200b8061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106102ef575f3560e01c80638c1ac18a1161019b578063c5f956af116100e7578063e0f6123d116100a0578063e87554461161007a578063e8755446146108fe578063f445d70314610907578063f851a44014610934578063fa6331d814610946576102ef565b8063e0f6123d14610892578063e37d4b79146108b4578063e57e69c6146108eb576102ef565b8063c5f956af1461079d578063c7ee005e146107b0578063cdffacc6146107c3578063d3270f9914610859578063dce154491461086c578063dcfbc0c71461087f576102ef565b8063a657e57911610154578063b8324c7c1161012e578063b8324c7c14610707578063bb82aa5e14610762578063bbb8864a14610775578063bec04f7214610794576102ef565b8063a657e579146106c1578063adfca15e146106d4578063b2eafc39146106f4576102ef565b80638c1ac18a146106235780638f738f36146106455780639254f5e51461067057806394b2294b1461068357806396c990641461068c5780639bb27d62146106ae576102ef565b8063425fad581161025a57806373769099116102135780637d172bd5116101ed5780637d172bd5146105d15780637dc0d1d0146105e45780637fb8e8cd146105f75780638a7dc16514610604576102ef565b8063737690991461056a57806376551383146105aa5780637a0ed627146105bc576102ef565b8063425fad58146104e85780634a584432146104fb57806352d84d1e1461051a57806352ef6b2c1461052d5780635dd3fc9d14610542578063719f701b14610561576102ef565b806321af4569116102ac57806321af45691461044157806324a3d6221461046c578063267822471461047f5780632bc7e29e146104925780634088c73e146104b157806341a18d2c146104be576102ef565b806302c3bcbb1461038357806304ef9d58146103b557806308e0225c146103be5780630db4b4e5146103e857806310b98338146103f15780631d504dc61461042e575b5f80356001600160e01b0319168152602e60205260409020546001600160a01b0316806103635760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b365f80375f80365f845af43d5f803e80801561037d573d5ff35b3d5ffd5b005b6103a2610391366004611939565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103a260225481565b6103a26103cc36600461195b565b601360209081525f928352604080842090915290825290205481565b6103a2601d5481565b61041e6103ff36600461195b565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103ac565b61038161043c366004611939565b61094f565b601e54610454906001600160a01b031681565b6040516001600160a01b0390911681526020016103ac565b600a54610454906001600160a01b031681565b600154610454906001600160a01b031681565b6103a26104a0366004611939565b60166020525f908152604090205481565b60185461041e9060ff1681565b6103a26104cc36600461195b565b601260209081525f928352604080842090915290825290205481565b60185461041e9062010000900460ff1681565b6103a2610509366004611939565b601f6020525f908152604090205481565b610454610528366004611992565b610aad565b610535610ad5565b6040516103ac91906119a9565b6103a2610550366004611939565b602b6020525f908152604090205481565b6103a2601c5481565b610592610578366004611939565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103ac565b60185461041e90610100900460ff1681565b6105c4610b35565b6040516103ac9190611a39565b601b54610454906001600160a01b031681565b600454610454906001600160a01b031681565b60395461041e9060ff1681565b6103a2610612366004611939565b60146020525f908152604090205481565b61041e610631366004611939565b602d6020525f908152604090205460ff1681565b6103a2610653366004611939565b6001600160a01b03165f908152602f602052604090206001015490565b601554610454906001600160a01b031681565b6103a260075481565b61069f61069a366004611ab6565b610cb9565b6040516103ac93929190611b0a565b602554610454906001600160a01b031681565b603754610592906001600160601b031681565b6106e76106e2366004611939565b610d66565b6040516103ac9190611b33565b602054610454906001600160a01b031681565b61073e610715366004611939565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103ac565b600254610454906001600160a01b031681565b6103a2610783366004611939565b602a6020525f908152604090205481565b6103a260175481565b602154610454906001600160a01b031681565b603154610454906001600160a01b031681565b61082c6107d1366004611b61565b604080518082019091525f8082526020820152506001600160e01b0319165f908152602e60209081526040918290208251808401909352546001600160a01b0381168352600160a01b90046001600160601b03169082015290565b6040805182516001600160a01b031681526020928301516001600160601b031692810192909252016103ac565b602654610454906001600160a01b031681565b61045461087a366004611b7a565b610dfb565b600354610454906001600160a01b031681565b61041e6108a0366004611939565b60386020525f908152604090205460ff1681565b61073e6108c2366004611939565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6103816108f9366004611c35565b610e2f565b6103a260055481565b61041e61091536600461195b565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610454906001600160a01b031681565b6103a2601a5481565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109af9190611d9b565b6001600160a01b0316336001600160a01b031614610a0b5760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b604482015260640161035a565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6c9190611db6565b15610aaa5760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b604482015260640161035a565b50565b600d8181548110610abc575f80fd5b5f918252602090912001546001600160a01b0316905081565b60606030805480602002602001604051908101604052809291908181526020018280548015610b2b57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610b0d575b5050505050905090565b6030546060905f8167ffffffffffffffff811115610b5557610b55611ba4565b604051908082528060200260200182016040528015610b9a57816020015b604080518082019091525f815260606020820152815260200190600190039081610b735790505b5090505f5b82811015610cb2575f60308281548110610bbb57610bbb611dcd565b905f5260205f20015f9054906101000a90046001600160a01b0316905080838381518110610beb57610beb611dcd565b6020908102919091018101516001600160a01b0392831690529082165f908152602f825260409081902080548251818502810185019093528083529192909190830182828015610c8457602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610c465790505b5050505050838381518110610c9b57610c9b611dcd565b602090810291909101810151015250600101610b9f565b5092915050565b60366020525f9081526040902080548190610cd390611de1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cff90611de1565b8015610d4a5780601f10610d2157610100808354040283529160200191610d4a565b820191905f5260205f20905b815481529060010190602001808311610d2d57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6001600160a01b0381165f908152602f6020908152604091829020805483518184028101840190945280845260609392830182828015610def57602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610db15790505b50505050509050919050565b6008602052815f5260405f208181548110610e14575f80fd5b5f918252602090912001546001600160a01b03169150829050565b5f546001600160a01b03163314610e845760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b604482015260640161035a565b610aaa8180515f5b8181101561103f575f838281518110610ea757610ea7611dcd565b60200260200101516020015190505f6002811115610ec757610ec7611e19565b816002811115610ed957610ed9611e19565b03610f2657610f21848381518110610ef357610ef3611dcd565b60200260200101515f0151858481518110610f1057610f10611dcd565b60200260200101516040015161107b565b611036565b6001816002811115610f3a57610f3a611e19565b03610f8257610f21848381518110610f5457610f54611dcd565b60200260200101515f0151858481518110610f7157610f71611dcd565b6020026020010151604001516111da565b6002816002811115610f9657610f96611e19565b03610fde57610f21848381518110610fb057610fb0611dcd565b60200260200101515f0151858481518110610fcd57610fcd611dcd565b602002602001015160400151611349565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b606482015260840161035a565b50600101610e8c565b507f2e97860c6f47eab0292d51fa3ceec7e373c62af1e7eb2a28ae82998b80de6cfd8260405161106f9190611e2d565b60405180910390a15050565b80515f0361109b5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b0382166110c15760405162461bcd60e51b815260040161035a90611f11565b6001600160a01b0382165f908152602f6020526040812054906001600160601b03821690036110f3576110f38361144a565b81515f5b818110156111d3575f84828151811061111257611112611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031680156111b05760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b606482015260840161035a565b6111bb8286896114ec565b6111c485611f71565b945050508060010190506110f7565b5050505050565b80515f036111fa5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b0382166112205760405162461bcd60e51b815260040161035a90611f11565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611252576112528361144a565b81515f5b818110156111d3575f84828151811061127157611271611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b03908116908716810361131c5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606482015260840161035a565b611326818361158a565b6113318286896114ec565b61133a85611f71565b94505050806001019050611256565b80515f81900361136b5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b038316156113e15760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b606482015260840161035a565b5f5b81811015611444575f8382815181106113fe576113fe611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031661143a818361158a565b50506001016113e3565b50505050565b611489816040518060400160405280601e81526020017f4469616d6f6e643a204e657720666163657420686173206e6f20636f646500008152506118cf565b603080546001600160a01b039092165f818152602f60205260408120600190810185905584018355919091527f6ff97a59c90d62cc7236ba3a37cd85351bf564556780cf8c1157a220f31f0cbb90910180546001600160a01b0319169091179055565b6001600160e01b031983165f818152602e6020818152604080842080546001600160601b03909816600160a01b026001600160a01b0398891617815595909616808452602f825295832080546001810182559084528184206008820401805460e09990991c60046007909316929092026101000a91820263ffffffff909202199098161790965591905290925281546001600160a01b031916179055565b6001600160a01b0382166116065760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606482015260840161035a565b6001600160e01b031981165f908152602e60209081526040808320546001600160a01b0386168452602f909252822054600160a01b9091046001600160601b0316919061165590600190611f96565b9050808214611741576001600160a01b0384165f908152602f6020526040812080548390811061168757611687611dcd565b5f91825260208083206008830401546001600160a01b0389168452602f9091526040909220805460079092166004026101000a90920460e01b9250829190859081106116d5576116d5611dcd565b5f91825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b0319929092168252602e90526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384165f908152602f6020526040902080548061176757611767611faf565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252602e905260408120819055819003611444576030545f906117c690600190611f96565b6001600160a01b0386165f908152602f602052604090206001015490915080821461186a575f603083815481106117ff576117ff611dcd565b5f91825260209091200154603080546001600160a01b03909216925082918490811061182d5761182d611dcd565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152602f909152604090206001018190555b603080548061187b5761187b611faf565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092556001600160a01b0388168252602f905260408120906118be82826118f0565b600182015f90555050505050505050565b813b81816114445760405162461bcd60e51b815260040161035a9190611fc3565b5080545f825560070160089004905f5260205f2090810190610aaa91905b80821115611921575f815560010161190e565b5090565b6001600160a01b0381168114610aaa575f80fd5b5f60208284031215611949575f80fd5b813561195481611925565b9392505050565b5f806040838503121561196c575f80fd5b823561197781611925565b9150602083013561198781611925565b809150509250929050565b5f602082840312156119a2575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b818110156119e95783516001600160a01b0316835292840192918401916001016119c4565b50909695505050505050565b5f815180845260208085019450602084015f5b83811015611a2e5781516001600160e01b03191687529582019590820190600101611a08565b509495945050505050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611aa857888303603f19018552815180516001600160a01b03168452870151878401879052611a95878501826119f5565b9588019593505090860190600101611a60565b509098975050505050505050565b5f60208284031215611ac6575f80fd5b81356001600160601b0381168114611954575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f611b1c6060830186611adc565b931515602083015250901515604090910152919050565b602081525f61195460208301846119f5565b80356001600160e01b031981168114611b5c575f80fd5b919050565b5f60208284031215611b71575f80fd5b61195482611b45565b5f8060408385031215611b8b575f80fd5b8235611b9681611925565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611bdb57611bdb611ba4565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c0a57611c0a611ba4565b604052919050565b5f67ffffffffffffffff821115611c2b57611c2b611ba4565b5060051b60200190565b5f6020808385031215611c46575f80fd5b823567ffffffffffffffff80821115611c5d575f80fd5b818501915085601f830112611c70575f80fd5b8135611c83611c7e82611c12565b611be1565b81815260059190911b83018401908481019088831115611ca1575f80fd5b8585015b83811015611d8e57803585811115611cbb575f80fd5b86016060818c03601f1901811315611cd1575f80fd5b611cd9611bb8565b89830135611ce681611925565b815260408381013560038110611cfa575f80fd5b828c0152918301359188831115611d0f575f80fd5b82840193508d603f850112611d22575f80fd5b8a8401359250611d34611c7e84611c12565b83815260059390931b84018101928b8101908f851115611d52575f80fd5b948201945b84861015611d7757611d6886611b45565b8252948c0194908c0190611d57565b918301919091525085525050918601918601611ca5565b5098975050505050505050565b5f60208284031215611dab575f80fd5b815161195481611925565b5f60208284031215611dc6575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680611df557607f821691505b602082108103611e1357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611aa857888303603f19018552815180516001600160a01b031684528781015160609060038110611e9757634e487b7160e01b5f52602160045260245ffd5b858a01529087015187850182905290611eb2818601836119f5565b968901969450505090860190600101611e54565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160601b03808316818103611f8c57611f8c611f5d565b6001019392505050565b81810381811115611fa957611fa9611f5d565b92915050565b634e487b7160e01b5f52603160045260245ffd5b602081525f6119546020830184611adc56fea2646970667358221220a6be7462800b74f95572f969b57a5a0d99898d128b76aa663e604dc84fd8cbca64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102ef575f3560e01c80638c1ac18a1161019b578063c5f956af116100e7578063e0f6123d116100a0578063e87554461161007a578063e8755446146108fe578063f445d70314610907578063f851a44014610934578063fa6331d814610946576102ef565b8063e0f6123d14610892578063e37d4b79146108b4578063e57e69c6146108eb576102ef565b8063c5f956af1461079d578063c7ee005e146107b0578063cdffacc6146107c3578063d3270f9914610859578063dce154491461086c578063dcfbc0c71461087f576102ef565b8063a657e57911610154578063b8324c7c1161012e578063b8324c7c14610707578063bb82aa5e14610762578063bbb8864a14610775578063bec04f7214610794576102ef565b8063a657e579146106c1578063adfca15e146106d4578063b2eafc39146106f4576102ef565b80638c1ac18a146106235780638f738f36146106455780639254f5e51461067057806394b2294b1461068357806396c990641461068c5780639bb27d62146106ae576102ef565b8063425fad581161025a57806373769099116102135780637d172bd5116101ed5780637d172bd5146105d15780637dc0d1d0146105e45780637fb8e8cd146105f75780638a7dc16514610604576102ef565b8063737690991461056a57806376551383146105aa5780637a0ed627146105bc576102ef565b8063425fad58146104e85780634a584432146104fb57806352d84d1e1461051a57806352ef6b2c1461052d5780635dd3fc9d14610542578063719f701b14610561576102ef565b806321af4569116102ac57806321af45691461044157806324a3d6221461046c578063267822471461047f5780632bc7e29e146104925780634088c73e146104b157806341a18d2c146104be576102ef565b806302c3bcbb1461038357806304ef9d58146103b557806308e0225c146103be5780630db4b4e5146103e857806310b98338146103f15780631d504dc61461042e575b5f80356001600160e01b0319168152602e60205260409020546001600160a01b0316806103635760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b365f80375f80365f845af43d5f803e80801561037d573d5ff35b3d5ffd5b005b6103a2610391366004611939565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103a260225481565b6103a26103cc36600461195b565b601360209081525f928352604080842090915290825290205481565b6103a2601d5481565b61041e6103ff36600461195b565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103ac565b61038161043c366004611939565b61094f565b601e54610454906001600160a01b031681565b6040516001600160a01b0390911681526020016103ac565b600a54610454906001600160a01b031681565b600154610454906001600160a01b031681565b6103a26104a0366004611939565b60166020525f908152604090205481565b60185461041e9060ff1681565b6103a26104cc36600461195b565b601260209081525f928352604080842090915290825290205481565b60185461041e9062010000900460ff1681565b6103a2610509366004611939565b601f6020525f908152604090205481565b610454610528366004611992565b610aad565b610535610ad5565b6040516103ac91906119a9565b6103a2610550366004611939565b602b6020525f908152604090205481565b6103a2601c5481565b610592610578366004611939565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103ac565b60185461041e90610100900460ff1681565b6105c4610b35565b6040516103ac9190611a39565b601b54610454906001600160a01b031681565b600454610454906001600160a01b031681565b60395461041e9060ff1681565b6103a2610612366004611939565b60146020525f908152604090205481565b61041e610631366004611939565b602d6020525f908152604090205460ff1681565b6103a2610653366004611939565b6001600160a01b03165f908152602f602052604090206001015490565b601554610454906001600160a01b031681565b6103a260075481565b61069f61069a366004611ab6565b610cb9565b6040516103ac93929190611b0a565b602554610454906001600160a01b031681565b603754610592906001600160601b031681565b6106e76106e2366004611939565b610d66565b6040516103ac9190611b33565b602054610454906001600160a01b031681565b61073e610715366004611939565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103ac565b600254610454906001600160a01b031681565b6103a2610783366004611939565b602a6020525f908152604090205481565b6103a260175481565b602154610454906001600160a01b031681565b603154610454906001600160a01b031681565b61082c6107d1366004611b61565b604080518082019091525f8082526020820152506001600160e01b0319165f908152602e60209081526040918290208251808401909352546001600160a01b0381168352600160a01b90046001600160601b03169082015290565b6040805182516001600160a01b031681526020928301516001600160601b031692810192909252016103ac565b602654610454906001600160a01b031681565b61045461087a366004611b7a565b610dfb565b600354610454906001600160a01b031681565b61041e6108a0366004611939565b60386020525f908152604090205460ff1681565b61073e6108c2366004611939565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6103816108f9366004611c35565b610e2f565b6103a260055481565b61041e61091536600461195b565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610454906001600160a01b031681565b6103a2601a5481565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109af9190611d9b565b6001600160a01b0316336001600160a01b031614610a0b5760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b604482015260640161035a565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6c9190611db6565b15610aaa5760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b604482015260640161035a565b50565b600d8181548110610abc575f80fd5b5f918252602090912001546001600160a01b0316905081565b60606030805480602002602001604051908101604052809291908181526020018280548015610b2b57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610b0d575b5050505050905090565b6030546060905f8167ffffffffffffffff811115610b5557610b55611ba4565b604051908082528060200260200182016040528015610b9a57816020015b604080518082019091525f815260606020820152815260200190600190039081610b735790505b5090505f5b82811015610cb2575f60308281548110610bbb57610bbb611dcd565b905f5260205f20015f9054906101000a90046001600160a01b0316905080838381518110610beb57610beb611dcd565b6020908102919091018101516001600160a01b0392831690529082165f908152602f825260409081902080548251818502810185019093528083529192909190830182828015610c8457602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610c465790505b5050505050838381518110610c9b57610c9b611dcd565b602090810291909101810151015250600101610b9f565b5092915050565b60366020525f9081526040902080548190610cd390611de1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cff90611de1565b8015610d4a5780601f10610d2157610100808354040283529160200191610d4a565b820191905f5260205f20905b815481529060010190602001808311610d2d57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6001600160a01b0381165f908152602f6020908152604091829020805483518184028101840190945280845260609392830182828015610def57602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610db15790505b50505050509050919050565b6008602052815f5260405f208181548110610e14575f80fd5b5f918252602090912001546001600160a01b03169150829050565b5f546001600160a01b03163314610e845760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b604482015260640161035a565b610aaa8180515f5b8181101561103f575f838281518110610ea757610ea7611dcd565b60200260200101516020015190505f6002811115610ec757610ec7611e19565b816002811115610ed957610ed9611e19565b03610f2657610f21848381518110610ef357610ef3611dcd565b60200260200101515f0151858481518110610f1057610f10611dcd565b60200260200101516040015161107b565b611036565b6001816002811115610f3a57610f3a611e19565b03610f8257610f21848381518110610f5457610f54611dcd565b60200260200101515f0151858481518110610f7157610f71611dcd565b6020026020010151604001516111da565b6002816002811115610f9657610f96611e19565b03610fde57610f21848381518110610fb057610fb0611dcd565b60200260200101515f0151858481518110610fcd57610fcd611dcd565b602002602001015160400151611349565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b606482015260840161035a565b50600101610e8c565b507f2e97860c6f47eab0292d51fa3ceec7e373c62af1e7eb2a28ae82998b80de6cfd8260405161106f9190611e2d565b60405180910390a15050565b80515f0361109b5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b0382166110c15760405162461bcd60e51b815260040161035a90611f11565b6001600160a01b0382165f908152602f6020526040812054906001600160601b03821690036110f3576110f38361144a565b81515f5b818110156111d3575f84828151811061111257611112611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031680156111b05760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b606482015260840161035a565b6111bb8286896114ec565b6111c485611f71565b945050508060010190506110f7565b5050505050565b80515f036111fa5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b0382166112205760405162461bcd60e51b815260040161035a90611f11565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611252576112528361144a565b81515f5b818110156111d3575f84828151811061127157611271611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b03908116908716810361131c5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606482015260840161035a565b611326818361158a565b6113318286896114ec565b61133a85611f71565b94505050806001019050611256565b80515f81900361136b5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b038316156113e15760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b606482015260840161035a565b5f5b81811015611444575f8382815181106113fe576113fe611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031661143a818361158a565b50506001016113e3565b50505050565b611489816040518060400160405280601e81526020017f4469616d6f6e643a204e657720666163657420686173206e6f20636f646500008152506118cf565b603080546001600160a01b039092165f818152602f60205260408120600190810185905584018355919091527f6ff97a59c90d62cc7236ba3a37cd85351bf564556780cf8c1157a220f31f0cbb90910180546001600160a01b0319169091179055565b6001600160e01b031983165f818152602e6020818152604080842080546001600160601b03909816600160a01b026001600160a01b0398891617815595909616808452602f825295832080546001810182559084528184206008820401805460e09990991c60046007909316929092026101000a91820263ffffffff909202199098161790965591905290925281546001600160a01b031916179055565b6001600160a01b0382166116065760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606482015260840161035a565b6001600160e01b031981165f908152602e60209081526040808320546001600160a01b0386168452602f909252822054600160a01b9091046001600160601b0316919061165590600190611f96565b9050808214611741576001600160a01b0384165f908152602f6020526040812080548390811061168757611687611dcd565b5f91825260208083206008830401546001600160a01b0389168452602f9091526040909220805460079092166004026101000a90920460e01b9250829190859081106116d5576116d5611dcd565b5f91825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b0319929092168252602e90526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384165f908152602f6020526040902080548061176757611767611faf565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252602e905260408120819055819003611444576030545f906117c690600190611f96565b6001600160a01b0386165f908152602f602052604090206001015490915080821461186a575f603083815481106117ff576117ff611dcd565b5f91825260209091200154603080546001600160a01b03909216925082918490811061182d5761182d611dcd565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152602f909152604090206001018190555b603080548061187b5761187b611faf565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092556001600160a01b0388168252602f905260408120906118be82826118f0565b600182015f90555050505050505050565b813b81816114445760405162461bcd60e51b815260040161035a9190611fc3565b5080545f825560070160089004905f5260205f2090810190610aaa91905b80821115611921575f815560010161190e565b5090565b6001600160a01b0381168114610aaa575f80fd5b5f60208284031215611949575f80fd5b813561195481611925565b9392505050565b5f806040838503121561196c575f80fd5b823561197781611925565b9150602083013561198781611925565b809150509250929050565b5f602082840312156119a2575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b818110156119e95783516001600160a01b0316835292840192918401916001016119c4565b50909695505050505050565b5f815180845260208085019450602084015f5b83811015611a2e5781516001600160e01b03191687529582019590820190600101611a08565b509495945050505050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611aa857888303603f19018552815180516001600160a01b03168452870151878401879052611a95878501826119f5565b9588019593505090860190600101611a60565b509098975050505050505050565b5f60208284031215611ac6575f80fd5b81356001600160601b0381168114611954575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f611b1c6060830186611adc565b931515602083015250901515604090910152919050565b602081525f61195460208301846119f5565b80356001600160e01b031981168114611b5c575f80fd5b919050565b5f60208284031215611b71575f80fd5b61195482611b45565b5f8060408385031215611b8b575f80fd5b8235611b9681611925565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611bdb57611bdb611ba4565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c0a57611c0a611ba4565b604052919050565b5f67ffffffffffffffff821115611c2b57611c2b611ba4565b5060051b60200190565b5f6020808385031215611c46575f80fd5b823567ffffffffffffffff80821115611c5d575f80fd5b818501915085601f830112611c70575f80fd5b8135611c83611c7e82611c12565b611be1565b81815260059190911b83018401908481019088831115611ca1575f80fd5b8585015b83811015611d8e57803585811115611cbb575f80fd5b86016060818c03601f1901811315611cd1575f80fd5b611cd9611bb8565b89830135611ce681611925565b815260408381013560038110611cfa575f80fd5b828c0152918301359188831115611d0f575f80fd5b82840193508d603f850112611d22575f80fd5b8a8401359250611d34611c7e84611c12565b83815260059390931b84018101928b8101908f851115611d52575f80fd5b948201945b84861015611d7757611d6886611b45565b8252948c0194908c0190611d57565b918301919091525085525050918601918601611ca5565b5098975050505050505050565b5f60208284031215611dab575f80fd5b815161195481611925565b5f60208284031215611dc6575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680611df557607f821691505b602082108103611e1357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611aa857888303603f19018552815180516001600160a01b031684528781015160609060038110611e9757634e487b7160e01b5f52602160045260245ffd5b858a01529087015187850182905290611eb2818601836119f5565b968901969450505090860190600101611e54565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160601b03808316818103611f8c57611f8c611f5d565b6001019392505050565b81810381811115611fa957611fa9611f5d565b92915050565b634e487b7160e01b5f52603160045260245ffd5b602081525f6119546020830184611adc56fea2646970667358221220a6be7462800b74f95572f969b57a5a0d99898d128b76aa663e604dc84fd8cbca64736f6c63430008190033", + "numDeployments": 5, + "solcInputHash": "cbc4287e135101fe4c78448d0f5f2ecc", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"indexed\":false,\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"}],\"name\":\"DiamondCut\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"diamondCut_\",\"type\":\"tuple[]\"}],\"name\":\"diamondCut\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"functionSelector\",\"type\":\"bytes4\"}],\"name\":\"facetAddress\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"functionSelectorPosition\",\"type\":\"uint96\"}],\"internalType\":\"struct ComptrollerV13Storage.FacetAddressAndPosition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facetAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"facet\",\"type\":\"address\"}],\"name\":\"facetFunctionSelectors\",\"outputs\":[{\"internalType\":\"bytes4[]\",\"name\":\"\",\"type\":\"bytes4[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"facet\",\"type\":\"address\"}],\"name\":\"facetPosition\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facets\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct Diamond.Facet[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"_become(address)\":{\"params\":{\"unitroller\":\"Address of the unitroller\"}},\"diamondCut((address,uint8,bytes4[])[])\":{\"details\":\"Allows the contract admin to add function selectors\",\"params\":{\"diamondCut_\":\"IDiamondCut contains facets address, action and function selectors\"}},\"facetAddress(bytes4)\":{\"params\":{\"functionSelector\":\"function selector\"},\"returns\":{\"_0\":\"FacetAddressAndPosition facet address and position\"}},\"facetAddresses()\":{\"returns\":{\"_0\":\"facetAddresses Array of facet addresses\"}},\"facetFunctionSelectors(address)\":{\"params\":{\"facet\":\"Address of the facet\"},\"returns\":{\"_0\":\"selectors Array of function selectors\"}},\"facetPosition(address)\":{\"params\":{\"facet\":\"Address of the facet\"},\"returns\":{\"_0\":\"Position of the facet\"}},\"facets()\":{\"returns\":{\"_0\":\"facets_ Array of Facet\"}}},\"title\":\"Diamond\",\"version\":1},\"userdoc\":{\"events\":{\"DiamondCut((address,uint8,bytes4[])[])\":{\"notice\":\"Emitted when functions are added, replaced or removed to facets\"}},\"kind\":\"user\",\"methods\":{\"_become(address)\":{\"notice\":\"Call _acceptImplementation to accept the diamond proxy as new implementaion\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"diamondCut((address,uint8,bytes4[])[])\":{\"notice\":\"To add function selectors to the facet's mapping\"},\"facetAddress(bytes4)\":{\"notice\":\"Get facet address and position through function selector\"},\"facetAddresses()\":{\"notice\":\"Get all facet addresses\"},\"facetFunctionSelectors(address)\":{\"notice\":\"Get all function selectors mapped to the facet address\"},\"facetPosition(address)\":{\"notice\":\"Get facet position in the _facetFunctionSelectors through facet address\"},\"facets()\":{\"notice\":\"Get all facets address and their function selector\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This contract contains functions related to facets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/Diamond.sol\":\"Diamond\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\\n enum KeeperAction {\\n SetMinPrice,\\n SetMaxPrice,\\n ExitProtectionMode\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool cachingEnabled;\\n }\\n\\n /// @notice One item in an syncPriceBoundsAndProtections payload\\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\\n struct KeeperActionItem {\\n address asset;\\n KeeperAction action;\\n uint256 value;\\n }\\n\\n /// @notice One item in a setTokenConfigs payload\\n struct TokenConfigInput {\\n /// @notice The underlying asset address\\n address asset;\\n /// @notice Minimum time protection stays active after the last trigger (seconds)\\n uint64 cooldownPeriod;\\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\\n uint256 triggerThreshold;\\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\\n uint256 resetThreshold;\\n /// @notice Whether to enable bounded pricing immediately upon initialization\\n bool enableBoundedPricing;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool enableCaching;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n /// @notice Emitted when the per-asset transient caching flag is toggled\\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\\n error InvalidKeeperAction(uint8 action);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage. The transient\\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n /**\\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\\n * Empty `actions` is a no-op success.\\n * @param actions The list of keeper actions to apply\\n * @custom:access Only authorized keeper addresses\\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\\n */\\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param tokenConfig_ Token config input for the asset\\n * @custom:access Only Governance\\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param tokenConfigs_ Array of token config inputs, one per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if the input array is empty\\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\\n * @custom:error VAINotAllowed if any asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n /**\\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\\n * live spot instead of reading or writing the transient slots. The initial value is\\n * set via the `enableCaching` argument of `setTokenConfig`.\\n * @param asset The underlying asset address\\n * @param enabled Whether transient caching is enabled for this asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CachingEnabledUpdated\\n */\\n function setCachingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold,\\n bool cachingEnabled\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0xe223d88c17c0d752fdb33fa223b63ce124a798512f3d69f3800e9508e7dff931\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/Diamond.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IDiamondCut } from \\\"./interfaces/IDiamondCut.sol\\\";\\nimport { Unitroller } from \\\"../Unitroller.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../ComptrollerStorage.sol\\\";\\n\\n/**\\n * @title Diamond\\n * @author Venus\\n * @notice This contract contains functions related to facets\\n */\\ncontract Diamond is IDiamondCut, ComptrollerV19Storage {\\n /// @notice Emitted when functions are added, replaced or removed to facets\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut);\\n\\n struct Facet {\\n address facetAddress;\\n bytes4[] functionSelectors;\\n }\\n\\n /**\\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\\n * @param unitroller Address of the unitroller\\n */\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"not authorized\\\");\\n }\\n\\n /**\\n * @notice To add function selectors to the facet's mapping\\n * @dev Allows the contract admin to add function selectors\\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\\n */\\n function diamondCut(IDiamondCut.FacetCut[] memory diamondCut_) public {\\n require(msg.sender == admin, \\\"only unitroller admin can\\\");\\n libDiamondCut(diamondCut_);\\n }\\n\\n /**\\n * @notice Get all function selectors mapped to the facet address\\n * @param facet Address of the facet\\n * @return selectors Array of function selectors\\n */\\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\\n return _facetFunctionSelectors[facet].functionSelectors;\\n }\\n\\n /**\\n * @notice Get facet position in the _facetFunctionSelectors through facet address\\n * @param facet Address of the facet\\n * @return Position of the facet\\n */\\n function facetPosition(address facet) external view returns (uint256) {\\n return _facetFunctionSelectors[facet].facetAddressPosition;\\n }\\n\\n /**\\n * @notice Get all facet addresses\\n * @return facetAddresses Array of facet addresses\\n */\\n function facetAddresses() external view returns (address[] memory) {\\n return _facetAddresses;\\n }\\n\\n /**\\n * @notice Get facet address and position through function selector\\n * @param functionSelector function selector\\n * @return FacetAddressAndPosition facet address and position\\n */\\n function facetAddress(\\n bytes4 functionSelector\\n ) external view returns (ComptrollerV19Storage.FacetAddressAndPosition memory) {\\n return _selectorToFacetAndPosition[functionSelector];\\n }\\n\\n /**\\n * @notice Get all facets address and their function selector\\n * @return facets_ Array of Facet\\n */\\n function facets() external view returns (Facet[] memory) {\\n uint256 facetsLength = _facetAddresses.length;\\n Facet[] memory facets_ = new Facet[](facetsLength);\\n for (uint256 i; i < facetsLength; ++i) {\\n address facet = _facetAddresses[i];\\n facets_[i].facetAddress = facet;\\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\\n }\\n return facets_;\\n }\\n\\n /**\\n * @notice To add function selectors to the facets' mapping\\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\\n */\\n function libDiamondCut(IDiamondCut.FacetCut[] memory diamondCut_) internal {\\n uint256 diamondCutLength = diamondCut_.length;\\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\\n IDiamondCut.FacetCutAction action = diamondCut_[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(diamondCut_);\\n }\\n\\n /**\\n * @notice Add function selectors to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to add in the mapping\\n */\\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n require(functionSelectors.length != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n require(facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(facetAddress);\\n }\\n uint256 functionSelectorsLength = functionSelectors.length;\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(selector, selectorPosition, facetAddress);\\n ++selectorPosition;\\n }\\n }\\n\\n /**\\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to replace in the mapping\\n */\\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n require(functionSelectors.length != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n require(facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(facetAddress);\\n }\\n uint256 functionSelectorsLength = functionSelectors.length;\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(oldFacetAddress, selector);\\n addFunction(selector, selectorPosition, facetAddress);\\n ++selectorPosition;\\n }\\n }\\n\\n /**\\n * @notice Remove function selectors to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to remove in the mapping\\n */\\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n uint256 functionSelectorsLength = functionSelectors.length;\\n require(functionSelectorsLength != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n // if function does not exist then do nothing and revert\\n require(facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(oldFacetAddress, selector);\\n }\\n }\\n\\n /**\\n * @notice Add new facet to the proxy\\n * @param facetAddress Address of the facet\\n */\\n function addFacet(address facetAddress) internal {\\n enforceHasContractCode(facetAddress, \\\"Diamond: New facet has no code\\\");\\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\\n _facetAddresses.push(facetAddress);\\n }\\n\\n /**\\n * @notice Add function selector to the facet's address mapping\\n * @param selector funciton selector need to be added\\n * @param selectorPosition funciton selector position\\n * @param facetAddress Address of the facet\\n */\\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\\n }\\n\\n /**\\n * @notice Remove function selector to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param selector function selectors need to remove in the mapping\\n */\\n function removeFunction(address facetAddress, bytes4 selector) internal {\\n require(facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\\n // if not the same then replace selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\\n delete _selectorToFacetAndPosition[selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n _facetAddresses.pop();\\n delete _facetFunctionSelectors[facetAddress];\\n }\\n }\\n\\n /**\\n * @dev Ensure that the given address has contract code deployed\\n * @param _contract The address to check for contract code\\n * @param _errorMessage The error message to display if the contract code is not deployed\\n */\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize != 0, _errorMessage);\\n }\\n\\n // Find facet for function that is called and execute the\\n // function if a facet is found and return any value.\\n fallback() external {\\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\\n require(facet != address(0), \\\"Diamond: Function does not exist\\\");\\n // Execute public function from facet using delegatecall and return any value.\\n assembly {\\n // copy function selector and any arguments\\n calldatacopy(0, 0, calldatasize())\\n // execute function call using the facet\\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\\n // get any return value\\n returndatacopy(0, 0, returndatasize())\\n // return any return value or error back to the caller\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0517cc4bd5e654f8fa2084912a125bf7112122a896e1fc091f5351c4df89f4bb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n function diamondCut(FacetCut[] calldata _diamondCut) external;\\n}\\n\",\"keccak256\":\"0xcb93543c9122cf328715d2b242e99f8ca234bd1347d82290ad7a4e028f358141\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Unitroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { UnitrollerAdminStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../Utils/ErrorReporter.sol\\\";\\n\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * VTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n fallback() external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize())\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize())\\n }\\n default {\\n return(free_mem_ptr, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7e552ae197db0095044af62614b09426d3570bf15593aa7703be3a517287074b\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b5061203e8061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061030a575f3560e01c80638f738f361161019b578063c7ee005e116100e7578063e0f6123d116100a0578063e87554461161007a578063e875544614610931578063f445d7031461093a578063f851a44014610967578063fa6331d8146109795761030a565b8063e0f6123d146108c5578063e37d4b79146108e7578063e57e69c61461091e5761030a565b8063c7ee005e146107cb578063cdffacc6146107de578063d3270f9914610874578063d7c46d2d14610887578063dce154491461089f578063dcfbc0c7146108b25761030a565b8063adfca15e11610154578063bb82aa5e1161012e578063bb82aa5e1461077d578063bbb8864a14610790578063bec04f72146107af578063c5f956af146107b85761030a565b8063adfca15e146106ef578063b2eafc391461070f578063b8324c7c146107225761030a565b80638f738f36146106605780639254f5e51461068b57806394b2294b1461069e57806396c99064146106a75780639bb27d62146106c9578063a657e579146106dc5761030a565b80634a5844321161025a57806376551383116102135780637dc0d1d0116101ed5780637dc0d1d0146105ff5780637fb8e8cd146106125780638a7dc1651461061f5780638c1ac18a1461063e5761030a565b806376551383146105c55780637a0ed627146105d75780637d172bd5146105ec5761030a565b80634a5844321461051657806352d84d1e1461053557806352ef6b2c146105485780635dd3fc9d1461055d578063719f701b1461057c57806373769099146105855761030a565b806321af4569116102c75780632bc7e29e116102a15780632bc7e29e146104ad5780634088c73e146104cc57806341a18d2c146104d9578063425fad58146105035761030a565b806321af45691461045c57806324a3d62214610487578063267822471461049a5761030a565b806302c3bcbb1461039e57806304ef9d58146103d057806308e0225c146103d95780630db4b4e51461040357806310b983381461040c5780631d504dc614610449575b5f80356001600160e01b0319168152602e60205260409020546001600160a01b03168061037e5760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b365f80375f80365f845af43d5f803e808015610398573d5ff35b3d5ffd5b005b6103bd6103ac36600461196c565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103bd60225481565b6103bd6103e736600461198e565b601360209081525f928352604080842090915290825290205481565b6103bd601d5481565b61043961041a36600461198e565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103c7565b61039c61045736600461196c565b610982565b601e5461046f906001600160a01b031681565b6040516001600160a01b0390911681526020016103c7565b600a5461046f906001600160a01b031681565b60015461046f906001600160a01b031681565b6103bd6104bb36600461196c565b60166020525f908152604090205481565b6018546104399060ff1681565b6103bd6104e736600461198e565b601260209081525f928352604080842090915290825290205481565b6018546104399062010000900460ff1681565b6103bd61052436600461196c565b601f6020525f908152604090205481565b61046f6105433660046119c5565b610ae0565b610550610b08565b6040516103c791906119dc565b6103bd61056b36600461196c565b602b6020525f908152604090205481565b6103bd601c5481565b6105ad61059336600461196c565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103c7565b60185461043990610100900460ff1681565b6105df610b68565b6040516103c79190611a6c565b601b5461046f906001600160a01b031681565b60045461046f906001600160a01b031681565b6039546104399060ff1681565b6103bd61062d36600461196c565b60146020525f908152604090205481565b61043961064c36600461196c565b602d6020525f908152604090205460ff1681565b6103bd61066e36600461196c565b6001600160a01b03165f908152602f602052604090206001015490565b60155461046f906001600160a01b031681565b6103bd60075481565b6106ba6106b5366004611ae9565b610cec565b6040516103c793929190611b3d565b60255461046f906001600160a01b031681565b6037546105ad906001600160601b031681565b6107026106fd36600461196c565b610d99565b6040516103c79190611b66565b60205461046f906001600160a01b031681565b61075961073036600461196c565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103c7565b60025461046f906001600160a01b031681565b6103bd61079e36600461196c565b602a6020525f908152604090205481565b6103bd60175481565b60215461046f906001600160a01b031681565b60315461046f906001600160a01b031681565b6108476107ec366004611b94565b604080518082019091525f8082526020820152506001600160e01b0319165f908152602e60209081526040918290208251808401909352546001600160a01b0381168352600160a01b90046001600160601b03169082015290565b6040805182516001600160a01b031681526020928301516001600160601b031692810192909252016103c7565b60265461046f906001600160a01b031681565b60395461046f9061010090046001600160a01b031681565b61046f6108ad366004611bad565b610e2e565b60035461046f906001600160a01b031681565b6104396108d336600461196c565b60386020525f908152604090205460ff1681565b6107596108f536600461196c565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61039c61092c366004611c68565b610e62565b6103bd60055481565b61043961094836600461198e565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461046f906001600160a01b031681565b6103bd601a5481565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e29190611dce565b6001600160a01b0316336001600160a01b031614610a3e5760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b6044820152606401610375565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a9f9190611de9565b15610add5760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b6044820152606401610375565b50565b600d8181548110610aef575f80fd5b5f918252602090912001546001600160a01b0316905081565b60606030805480602002602001604051908101604052809291908181526020018280548015610b5e57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610b40575b5050505050905090565b6030546060905f8167ffffffffffffffff811115610b8857610b88611bd7565b604051908082528060200260200182016040528015610bcd57816020015b604080518082019091525f815260606020820152815260200190600190039081610ba65790505b5090505f5b82811015610ce5575f60308281548110610bee57610bee611e00565b905f5260205f20015f9054906101000a90046001600160a01b0316905080838381518110610c1e57610c1e611e00565b6020908102919091018101516001600160a01b0392831690529082165f908152602f825260409081902080548251818502810185019093528083529192909190830182828015610cb757602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610c795790505b5050505050838381518110610cce57610cce611e00565b602090810291909101810151015250600101610bd2565b5092915050565b60366020525f9081526040902080548190610d0690611e14565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3290611e14565b8015610d7d5780601f10610d5457610100808354040283529160200191610d7d565b820191905f5260205f20905b815481529060010190602001808311610d6057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6001600160a01b0381165f908152602f6020908152604091829020805483518184028101840190945280845260609392830182828015610e2257602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610de45790505b50505050509050919050565b6008602052815f5260405f208181548110610e47575f80fd5b5f918252602090912001546001600160a01b03169150829050565b5f546001600160a01b03163314610eb75760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b6044820152606401610375565b610add8180515f5b81811015611072575f838281518110610eda57610eda611e00565b60200260200101516020015190505f6002811115610efa57610efa611e4c565b816002811115610f0c57610f0c611e4c565b03610f5957610f54848381518110610f2657610f26611e00565b60200260200101515f0151858481518110610f4357610f43611e00565b6020026020010151604001516110ae565b611069565b6001816002811115610f6d57610f6d611e4c565b03610fb557610f54848381518110610f8757610f87611e00565b60200260200101515f0151858481518110610fa457610fa4611e00565b60200260200101516040015161120d565b6002816002811115610fc957610fc9611e4c565b0361101157610f54848381518110610fe357610fe3611e00565b60200260200101515f015185848151811061100057611000611e00565b60200260200101516040015161137c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401610375565b50600101610ebf565b507f2e97860c6f47eab0292d51fa3ceec7e373c62af1e7eb2a28ae82998b80de6cfd826040516110a29190611e60565b60405180910390a15050565b80515f036110ce5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b0382166110f45760405162461bcd60e51b815260040161037590611f44565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611126576111268361147d565b81515f5b81811015611206575f84828151811061114557611145611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031680156111e35760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b6064820152608401610375565b6111ee82868961151f565b6111f785611fa4565b9450505080600101905061112a565b5050505050565b80515f0361122d5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b0382166112535760405162461bcd60e51b815260040161037590611f44565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611285576112858361147d565b81515f5b81811015611206575f8482815181106112a4576112a4611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b03908116908716810361134f5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610375565b61135981836115bd565b61136482868961151f565b61136d85611fa4565b94505050806001019050611289565b80515f81900361139e5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b038316156114145760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b6064820152608401610375565b5f5b81811015611477575f83828151811061143157611431611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031661146d81836115bd565b5050600101611416565b50505050565b6114bc816040518060400160405280601e81526020017f4469616d6f6e643a204e657720666163657420686173206e6f20636f64650000815250611902565b603080546001600160a01b039092165f818152602f60205260408120600190810185905584018355919091527f6ff97a59c90d62cc7236ba3a37cd85351bf564556780cf8c1157a220f31f0cbb90910180546001600160a01b0319169091179055565b6001600160e01b031983165f818152602e6020818152604080842080546001600160601b03909816600160a01b026001600160a01b0398891617815595909616808452602f825295832080546001810182559084528184206008820401805460e09990991c60046007909316929092026101000a91820263ffffffff909202199098161790965591905290925281546001600160a01b031916179055565b6001600160a01b0382166116395760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610375565b6001600160e01b031981165f908152602e60209081526040808320546001600160a01b0386168452602f909252822054600160a01b9091046001600160601b0316919061168890600190611fc9565b9050808214611774576001600160a01b0384165f908152602f602052604081208054839081106116ba576116ba611e00565b5f91825260208083206008830401546001600160a01b0389168452602f9091526040909220805460079092166004026101000a90920460e01b92508291908590811061170857611708611e00565b5f91825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b0319929092168252602e90526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384165f908152602f6020526040902080548061179a5761179a611fe2565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252602e905260408120819055819003611477576030545f906117f990600190611fc9565b6001600160a01b0386165f908152602f602052604090206001015490915080821461189d575f6030838154811061183257611832611e00565b5f91825260209091200154603080546001600160a01b03909216925082918490811061186057611860611e00565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152602f909152604090206001018190555b60308054806118ae576118ae611fe2565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092556001600160a01b0388168252602f905260408120906118f18282611923565b600182015f90555050505050505050565b813b81816114775760405162461bcd60e51b81526004016103759190611ff6565b5080545f825560070160089004905f5260205f2090810190610add91905b80821115611954575f8155600101611941565b5090565b6001600160a01b0381168114610add575f80fd5b5f6020828403121561197c575f80fd5b813561198781611958565b9392505050565b5f806040838503121561199f575f80fd5b82356119aa81611958565b915060208301356119ba81611958565b809150509250929050565b5f602082840312156119d5575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b81811015611a1c5783516001600160a01b0316835292840192918401916001016119f7565b50909695505050505050565b5f815180845260208085019450602084015f5b83811015611a615781516001600160e01b03191687529582019590820190600101611a3b565b509495945050505050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611adb57888303603f19018552815180516001600160a01b03168452870151878401879052611ac887850182611a28565b9588019593505090860190600101611a93565b509098975050505050505050565b5f60208284031215611af9575f80fd5b81356001600160601b0381168114611987575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f611b4f6060830186611b0f565b931515602083015250901515604090910152919050565b602081525f6119876020830184611a28565b80356001600160e01b031981168114611b8f575f80fd5b919050565b5f60208284031215611ba4575f80fd5b61198782611b78565b5f8060408385031215611bbe575f80fd5b8235611bc981611958565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611c0e57611c0e611bd7565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c3d57611c3d611bd7565b604052919050565b5f67ffffffffffffffff821115611c5e57611c5e611bd7565b5060051b60200190565b5f6020808385031215611c79575f80fd5b823567ffffffffffffffff80821115611c90575f80fd5b818501915085601f830112611ca3575f80fd5b8135611cb6611cb182611c45565b611c14565b81815260059190911b83018401908481019088831115611cd4575f80fd5b8585015b83811015611dc157803585811115611cee575f80fd5b86016060818c03601f1901811315611d04575f80fd5b611d0c611beb565b89830135611d1981611958565b815260408381013560038110611d2d575f80fd5b828c0152918301359188831115611d42575f80fd5b82840193508d603f850112611d55575f80fd5b8a8401359250611d67611cb184611c45565b83815260059390931b84018101928b8101908f851115611d85575f80fd5b948201945b84861015611daa57611d9b86611b78565b8252948c0194908c0190611d8a565b918301919091525085525050918601918601611cd8565b5098975050505050505050565b5f60208284031215611dde575f80fd5b815161198781611958565b5f60208284031215611df9575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680611e2857607f821691505b602082108103611e4657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611adb57888303603f19018552815180516001600160a01b031684528781015160609060038110611eca57634e487b7160e01b5f52602160045260245ffd5b858a01529087015187850182905290611ee581860183611a28565b968901969450505090860190600101611e87565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160601b03808316818103611fbf57611fbf611f90565b6001019392505050565b81810381811115611fdc57611fdc611f90565b92915050565b634e487b7160e01b5f52603160045260245ffd5b602081525f6119876020830184611b0f56fea2646970667358221220bc5fa13880534200c1557c0535bc673fd2e8af1da3ab4a0d9e9041de2cb0037664736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061030a575f3560e01c80638f738f361161019b578063c7ee005e116100e7578063e0f6123d116100a0578063e87554461161007a578063e875544614610931578063f445d7031461093a578063f851a44014610967578063fa6331d8146109795761030a565b8063e0f6123d146108c5578063e37d4b79146108e7578063e57e69c61461091e5761030a565b8063c7ee005e146107cb578063cdffacc6146107de578063d3270f9914610874578063d7c46d2d14610887578063dce154491461089f578063dcfbc0c7146108b25761030a565b8063adfca15e11610154578063bb82aa5e1161012e578063bb82aa5e1461077d578063bbb8864a14610790578063bec04f72146107af578063c5f956af146107b85761030a565b8063adfca15e146106ef578063b2eafc391461070f578063b8324c7c146107225761030a565b80638f738f36146106605780639254f5e51461068b57806394b2294b1461069e57806396c99064146106a75780639bb27d62146106c9578063a657e579146106dc5761030a565b80634a5844321161025a57806376551383116102135780637dc0d1d0116101ed5780637dc0d1d0146105ff5780637fb8e8cd146106125780638a7dc1651461061f5780638c1ac18a1461063e5761030a565b806376551383146105c55780637a0ed627146105d75780637d172bd5146105ec5761030a565b80634a5844321461051657806352d84d1e1461053557806352ef6b2c146105485780635dd3fc9d1461055d578063719f701b1461057c57806373769099146105855761030a565b806321af4569116102c75780632bc7e29e116102a15780632bc7e29e146104ad5780634088c73e146104cc57806341a18d2c146104d9578063425fad58146105035761030a565b806321af45691461045c57806324a3d62214610487578063267822471461049a5761030a565b806302c3bcbb1461039e57806304ef9d58146103d057806308e0225c146103d95780630db4b4e51461040357806310b983381461040c5780631d504dc614610449575b5f80356001600160e01b0319168152602e60205260409020546001600160a01b03168061037e5760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b365f80375f80365f845af43d5f803e808015610398573d5ff35b3d5ffd5b005b6103bd6103ac36600461196c565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103bd60225481565b6103bd6103e736600461198e565b601360209081525f928352604080842090915290825290205481565b6103bd601d5481565b61043961041a36600461198e565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103c7565b61039c61045736600461196c565b610982565b601e5461046f906001600160a01b031681565b6040516001600160a01b0390911681526020016103c7565b600a5461046f906001600160a01b031681565b60015461046f906001600160a01b031681565b6103bd6104bb36600461196c565b60166020525f908152604090205481565b6018546104399060ff1681565b6103bd6104e736600461198e565b601260209081525f928352604080842090915290825290205481565b6018546104399062010000900460ff1681565b6103bd61052436600461196c565b601f6020525f908152604090205481565b61046f6105433660046119c5565b610ae0565b610550610b08565b6040516103c791906119dc565b6103bd61056b36600461196c565b602b6020525f908152604090205481565b6103bd601c5481565b6105ad61059336600461196c565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103c7565b60185461043990610100900460ff1681565b6105df610b68565b6040516103c79190611a6c565b601b5461046f906001600160a01b031681565b60045461046f906001600160a01b031681565b6039546104399060ff1681565b6103bd61062d36600461196c565b60146020525f908152604090205481565b61043961064c36600461196c565b602d6020525f908152604090205460ff1681565b6103bd61066e36600461196c565b6001600160a01b03165f908152602f602052604090206001015490565b60155461046f906001600160a01b031681565b6103bd60075481565b6106ba6106b5366004611ae9565b610cec565b6040516103c793929190611b3d565b60255461046f906001600160a01b031681565b6037546105ad906001600160601b031681565b6107026106fd36600461196c565b610d99565b6040516103c79190611b66565b60205461046f906001600160a01b031681565b61075961073036600461196c565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103c7565b60025461046f906001600160a01b031681565b6103bd61079e36600461196c565b602a6020525f908152604090205481565b6103bd60175481565b60215461046f906001600160a01b031681565b60315461046f906001600160a01b031681565b6108476107ec366004611b94565b604080518082019091525f8082526020820152506001600160e01b0319165f908152602e60209081526040918290208251808401909352546001600160a01b0381168352600160a01b90046001600160601b03169082015290565b6040805182516001600160a01b031681526020928301516001600160601b031692810192909252016103c7565b60265461046f906001600160a01b031681565b60395461046f9061010090046001600160a01b031681565b61046f6108ad366004611bad565b610e2e565b60035461046f906001600160a01b031681565b6104396108d336600461196c565b60386020525f908152604090205460ff1681565b6107596108f536600461196c565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61039c61092c366004611c68565b610e62565b6103bd60055481565b61043961094836600461198e565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461046f906001600160a01b031681565b6103bd601a5481565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e29190611dce565b6001600160a01b0316336001600160a01b031614610a3e5760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b6044820152606401610375565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a9f9190611de9565b15610add5760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b6044820152606401610375565b50565b600d8181548110610aef575f80fd5b5f918252602090912001546001600160a01b0316905081565b60606030805480602002602001604051908101604052809291908181526020018280548015610b5e57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610b40575b5050505050905090565b6030546060905f8167ffffffffffffffff811115610b8857610b88611bd7565b604051908082528060200260200182016040528015610bcd57816020015b604080518082019091525f815260606020820152815260200190600190039081610ba65790505b5090505f5b82811015610ce5575f60308281548110610bee57610bee611e00565b905f5260205f20015f9054906101000a90046001600160a01b0316905080838381518110610c1e57610c1e611e00565b6020908102919091018101516001600160a01b0392831690529082165f908152602f825260409081902080548251818502810185019093528083529192909190830182828015610cb757602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610c795790505b5050505050838381518110610cce57610cce611e00565b602090810291909101810151015250600101610bd2565b5092915050565b60366020525f9081526040902080548190610d0690611e14565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3290611e14565b8015610d7d5780601f10610d5457610100808354040283529160200191610d7d565b820191905f5260205f20905b815481529060010190602001808311610d6057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6001600160a01b0381165f908152602f6020908152604091829020805483518184028101840190945280845260609392830182828015610e2257602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610de45790505b50505050509050919050565b6008602052815f5260405f208181548110610e47575f80fd5b5f918252602090912001546001600160a01b03169150829050565b5f546001600160a01b03163314610eb75760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b6044820152606401610375565b610add8180515f5b81811015611072575f838281518110610eda57610eda611e00565b60200260200101516020015190505f6002811115610efa57610efa611e4c565b816002811115610f0c57610f0c611e4c565b03610f5957610f54848381518110610f2657610f26611e00565b60200260200101515f0151858481518110610f4357610f43611e00565b6020026020010151604001516110ae565b611069565b6001816002811115610f6d57610f6d611e4c565b03610fb557610f54848381518110610f8757610f87611e00565b60200260200101515f0151858481518110610fa457610fa4611e00565b60200260200101516040015161120d565b6002816002811115610fc957610fc9611e4c565b0361101157610f54848381518110610fe357610fe3611e00565b60200260200101515f015185848151811061100057611000611e00565b60200260200101516040015161137c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401610375565b50600101610ebf565b507f2e97860c6f47eab0292d51fa3ceec7e373c62af1e7eb2a28ae82998b80de6cfd826040516110a29190611e60565b60405180910390a15050565b80515f036110ce5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b0382166110f45760405162461bcd60e51b815260040161037590611f44565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611126576111268361147d565b81515f5b81811015611206575f84828151811061114557611145611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031680156111e35760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b6064820152608401610375565b6111ee82868961151f565b6111f785611fa4565b9450505080600101905061112a565b5050505050565b80515f0361122d5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b0382166112535760405162461bcd60e51b815260040161037590611f44565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611285576112858361147d565b81515f5b81811015611206575f8482815181106112a4576112a4611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b03908116908716810361134f5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610375565b61135981836115bd565b61136482868961151f565b61136d85611fa4565b94505050806001019050611289565b80515f81900361139e5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b038316156114145760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b6064820152608401610375565b5f5b81811015611477575f83828151811061143157611431611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031661146d81836115bd565b5050600101611416565b50505050565b6114bc816040518060400160405280601e81526020017f4469616d6f6e643a204e657720666163657420686173206e6f20636f64650000815250611902565b603080546001600160a01b039092165f818152602f60205260408120600190810185905584018355919091527f6ff97a59c90d62cc7236ba3a37cd85351bf564556780cf8c1157a220f31f0cbb90910180546001600160a01b0319169091179055565b6001600160e01b031983165f818152602e6020818152604080842080546001600160601b03909816600160a01b026001600160a01b0398891617815595909616808452602f825295832080546001810182559084528184206008820401805460e09990991c60046007909316929092026101000a91820263ffffffff909202199098161790965591905290925281546001600160a01b031916179055565b6001600160a01b0382166116395760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610375565b6001600160e01b031981165f908152602e60209081526040808320546001600160a01b0386168452602f909252822054600160a01b9091046001600160601b0316919061168890600190611fc9565b9050808214611774576001600160a01b0384165f908152602f602052604081208054839081106116ba576116ba611e00565b5f91825260208083206008830401546001600160a01b0389168452602f9091526040909220805460079092166004026101000a90920460e01b92508291908590811061170857611708611e00565b5f91825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b0319929092168252602e90526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384165f908152602f6020526040902080548061179a5761179a611fe2565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252602e905260408120819055819003611477576030545f906117f990600190611fc9565b6001600160a01b0386165f908152602f602052604090206001015490915080821461189d575f6030838154811061183257611832611e00565b5f91825260209091200154603080546001600160a01b03909216925082918490811061186057611860611e00565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152602f909152604090206001018190555b60308054806118ae576118ae611fe2565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092556001600160a01b0388168252602f905260408120906118f18282611923565b600182015f90555050505050505050565b813b81816114775760405162461bcd60e51b81526004016103759190611ff6565b5080545f825560070160089004905f5260205f2090810190610add91905b80821115611954575f8155600101611941565b5090565b6001600160a01b0381168114610add575f80fd5b5f6020828403121561197c575f80fd5b813561198781611958565b9392505050565b5f806040838503121561199f575f80fd5b82356119aa81611958565b915060208301356119ba81611958565b809150509250929050565b5f602082840312156119d5575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b81811015611a1c5783516001600160a01b0316835292840192918401916001016119f7565b50909695505050505050565b5f815180845260208085019450602084015f5b83811015611a615781516001600160e01b03191687529582019590820190600101611a3b565b509495945050505050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611adb57888303603f19018552815180516001600160a01b03168452870151878401879052611ac887850182611a28565b9588019593505090860190600101611a93565b509098975050505050505050565b5f60208284031215611af9575f80fd5b81356001600160601b0381168114611987575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f611b4f6060830186611b0f565b931515602083015250901515604090910152919050565b602081525f6119876020830184611a28565b80356001600160e01b031981168114611b8f575f80fd5b919050565b5f60208284031215611ba4575f80fd5b61198782611b78565b5f8060408385031215611bbe575f80fd5b8235611bc981611958565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611c0e57611c0e611bd7565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c3d57611c3d611bd7565b604052919050565b5f67ffffffffffffffff821115611c5e57611c5e611bd7565b5060051b60200190565b5f6020808385031215611c79575f80fd5b823567ffffffffffffffff80821115611c90575f80fd5b818501915085601f830112611ca3575f80fd5b8135611cb6611cb182611c45565b611c14565b81815260059190911b83018401908481019088831115611cd4575f80fd5b8585015b83811015611dc157803585811115611cee575f80fd5b86016060818c03601f1901811315611d04575f80fd5b611d0c611beb565b89830135611d1981611958565b815260408381013560038110611d2d575f80fd5b828c0152918301359188831115611d42575f80fd5b82840193508d603f850112611d55575f80fd5b8a8401359250611d67611cb184611c45565b83815260059390931b84018101928b8101908f851115611d85575f80fd5b948201945b84861015611daa57611d9b86611b78565b8252948c0194908c0190611d8a565b918301919091525085525050918601918601611cd8565b5098975050505050505050565b5f60208284031215611dde575f80fd5b815161198781611958565b5f60208284031215611df9575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680611e2857607f821691505b602082108103611e4657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611adb57888303603f19018552815180516001600160a01b031684528781015160609060038110611eca57634e487b7160e01b5f52602160045260245ffd5b858a01529087015187850182905290611ee581860183611a28565b968901969450505090860190600101611e87565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160601b03808316818103611fbf57611fbf611f90565b6001019392505050565b81810381811115611fdc57611fdc611f90565b92915050565b634e487b7160e01b5f52603160045260245ffd5b602081525f6119876020830184611b0f56fea2646970667358221220bc5fa13880534200c1557c0535bc673fd2e8af1da3ab4a0d9e9041de2cb0037664736f6c63430008190033", "devdoc": { "author": "Venus", "kind": "dev", @@ -1024,6 +1037,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "diamondCut((address,uint8,bytes4[])[])": { "notice": "To add function selectors to the facet's mapping" }, @@ -1136,7 +1152,7 @@ "storageLayout": { "storage": [ { - "astId": 1677, + "astId": 9226, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "admin", "offset": 0, @@ -1144,7 +1160,7 @@ "type": "t_address" }, { - "astId": 1680, + "astId": 9229, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "pendingAdmin", "offset": 0, @@ -1152,7 +1168,7 @@ "type": "t_address" }, { - "astId": 1683, + "astId": 9232, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "comptrollerImplementation", "offset": 0, @@ -1160,7 +1176,7 @@ "type": "t_address" }, { - "astId": 1686, + "astId": 9235, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "pendingComptrollerImplementation", "offset": 0, @@ -1168,15 +1184,15 @@ "type": "t_address" }, { - "astId": 1693, + "astId": 9242, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)992" + "type": "t_contract(ResilientOracleInterface)7913" }, { - "astId": 1696, + "astId": 9245, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "closeFactorMantissa", "offset": 0, @@ -1184,7 +1200,7 @@ "type": "t_uint256" }, { - "astId": 1699, + "astId": 9248, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -1192,7 +1208,7 @@ "type": "t_uint256" }, { - "astId": 1702, + "astId": 9251, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "maxAssets", "offset": 0, @@ -1200,23 +1216,23 @@ "type": "t_uint256" }, { - "astId": 1709, + "astId": 9258, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)" }, { - "astId": 1743, + "astId": 9292, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)" }, { - "astId": 1746, + "astId": 9295, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "pauseGuardian", "offset": 0, @@ -1224,7 +1240,7 @@ "type": "t_address" }, { - "astId": 1749, + "astId": 9298, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_mintGuardianPaused", "offset": 20, @@ -1232,7 +1248,7 @@ "type": "t_bool" }, { - "astId": 1752, + "astId": 9301, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_borrowGuardianPaused", "offset": 21, @@ -1240,7 +1256,7 @@ "type": "t_bool" }, { - "astId": 1755, + "astId": 9304, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "transferGuardianPaused", "offset": 22, @@ -1248,7 +1264,7 @@ "type": "t_bool" }, { - "astId": 1758, + "astId": 9307, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "seizeGuardianPaused", "offset": 23, @@ -1256,7 +1272,7 @@ "type": "t_bool" }, { - "astId": 1763, + "astId": 9312, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "mintGuardianPaused", "offset": 0, @@ -1264,7 +1280,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1768, + "astId": 9317, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "borrowGuardianPaused", "offset": 0, @@ -1272,15 +1288,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1780, + "astId": 9329, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)32634)dyn_storage" + "type": "t_array(t_contract(VToken)49461)dyn_storage" }, { - "astId": 1783, + "astId": 9332, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusRate", "offset": 0, @@ -1288,7 +1304,7 @@ "type": "t_uint256" }, { - "astId": 1788, + "astId": 9337, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusSpeeds", "offset": 0, @@ -1296,23 +1312,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1794, + "astId": 9343, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1800, + "astId": 9349, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)" }, { - "astId": 1807, + "astId": 9356, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusSupplierIndex", "offset": 0, @@ -1320,7 +1336,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1814, + "astId": 9363, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusBorrowerIndex", "offset": 0, @@ -1328,7 +1344,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1819, + "astId": 9368, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusAccrued", "offset": 0, @@ -1336,15 +1352,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1823, + "astId": 9372, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)25733" + "type": "t_contract(VAIControllerInterface)42511" }, { - "astId": 1828, + "astId": 9377, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "mintedVAIs", "offset": 0, @@ -1352,7 +1368,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1831, + "astId": 9380, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "vaiMintRate", "offset": 0, @@ -1360,7 +1376,7 @@ "type": "t_uint256" }, { - "astId": 1834, + "astId": 9383, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "mintVAIGuardianPaused", "offset": 0, @@ -1368,7 +1384,7 @@ "type": "t_bool" }, { - "astId": 1836, + "astId": 9385, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "repayVAIGuardianPaused", "offset": 1, @@ -1376,7 +1392,7 @@ "type": "t_bool" }, { - "astId": 1839, + "astId": 9388, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "protocolPaused", "offset": 2, @@ -1384,7 +1400,7 @@ "type": "t_bool" }, { - "astId": 1842, + "astId": 9391, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusVAIRate", "offset": 0, @@ -1392,7 +1408,7 @@ "type": "t_uint256" }, { - "astId": 1848, + "astId": 9397, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusVAIVaultRate", "offset": 0, @@ -1400,7 +1416,7 @@ "type": "t_uint256" }, { - "astId": 1850, + "astId": 9399, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "vaiVaultAddress", "offset": 0, @@ -1408,7 +1424,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9401, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "releaseStartBlock", "offset": 0, @@ -1416,7 +1432,7 @@ "type": "t_uint256" }, { - "astId": 1854, + "astId": 9403, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "minReleaseAmount", "offset": 0, @@ -1424,7 +1440,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9409, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "borrowCapGuardian", "offset": 0, @@ -1432,7 +1448,7 @@ "type": "t_address" }, { - "astId": 1865, + "astId": 9414, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "borrowCaps", "offset": 0, @@ -1440,7 +1456,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1871, + "astId": 9420, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "treasuryGuardian", "offset": 0, @@ -1448,7 +1464,7 @@ "type": "t_address" }, { - "astId": 1874, + "astId": 9423, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "treasuryAddress", "offset": 0, @@ -1456,7 +1472,7 @@ "type": "t_address" }, { - "astId": 1877, + "astId": 9426, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "treasuryPercent", "offset": 0, @@ -1464,7 +1480,7 @@ "type": "t_uint256" }, { - "astId": 1885, + "astId": 9434, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusContributorSpeeds", "offset": 0, @@ -1472,7 +1488,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9439, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "lastContributorBlock", "offset": 0, @@ -1480,7 +1496,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1895, + "astId": 9444, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "liquidatorContract", "offset": 0, @@ -1488,15 +1504,15 @@ "type": "t_address" }, { - "astId": 1901, + "astId": 9450, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1660" + "type": "t_contract(ComptrollerLensInterface)9207" }, { - "astId": 1909, + "astId": 9458, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "supplyCaps", "offset": 0, @@ -1504,7 +1520,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1915, + "astId": 9464, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "accessControl", "offset": 0, @@ -1512,7 +1528,7 @@ "type": "t_address" }, { - "astId": 1922, + "astId": 9471, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_actionPaused", "offset": 0, @@ -1520,7 +1536,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1930, + "astId": 9479, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusBorrowSpeeds", "offset": 0, @@ -1528,7 +1544,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1935, + "astId": 9484, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusSupplySpeeds", "offset": 0, @@ -1536,7 +1552,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1945, + "astId": 9494, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "approvedDelegates", "offset": 0, @@ -1544,7 +1560,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1953, + "astId": 9502, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -1552,23 +1568,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1972, + "astId": 9521, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)" }, { - "astId": 1977, + "astId": 9526, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)" }, { - "astId": 1980, + "astId": 9529, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_facetAddresses", "offset": 0, @@ -1576,15 +1592,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1987, + "astId": 9536, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)22911" + "type": "t_contract(IPrime)33730" }, { - "astId": 1997, + "astId": 9546, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -1592,7 +1608,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 2003, + "astId": 9552, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "xvs", "offset": 0, @@ -1600,7 +1616,7 @@ "type": "t_address" }, { - "astId": 2006, + "astId": 9555, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "xvsVToken", "offset": 0, @@ -1608,7 +1624,7 @@ "type": "t_address" }, { - "astId": 2028, + "astId": 9577, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "userPoolId", "offset": 0, @@ -1616,15 +1632,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2034, + "astId": 9583, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)2023_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)9572_storage)" }, { - "astId": 2037, + "astId": 9586, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "lastPoolId", "offset": 0, @@ -1632,7 +1648,7 @@ "type": "t_uint96" }, { - "astId": 2045, + "astId": 9594, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "authorizedFlashLoan", "offset": 0, @@ -1640,12 +1656,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2048, + "astId": 9597, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 9604, + "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)7883" } ], "types": { @@ -1666,8 +1690,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)32634)dyn_storage": { - "base": "t_contract(VToken)32634", + "t_array(t_contract(VToken)49461)dyn_storage": { + "base": "t_contract(VToken)49461", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -1682,37 +1706,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1660": { + "t_contract(ComptrollerLensInterface)9207": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)22911": { + "t_contract(IDeviationBoundedOracle)7883": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)33730": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)992": { + "t_contract(ResilientOracleInterface)7913": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)25733": { + "t_contract(VAIControllerInterface)42511": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)32634": { + "t_contract(VToken)49461": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)49461)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)32634)dyn_storage" + "value": "t_array(t_contract(VToken)49461)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -1742,19 +1771,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)9516_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1967_storage" + "value": "t_struct(FacetFunctionSelectors)9516_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9324_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1775_storage" + "value": "t_struct(VenusMarketState)9324_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -1770,12 +1799,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)9510_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1961_storage" + "value": "t_struct(FacetAddressAndPosition)9510_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -1784,31 +1813,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)2023_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)9572_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)2023_storage" + "value": "t_struct(PoolData)9572_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19217,t_struct(Market)9285_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11427", + "key": "t_userDefinedValueType(PoolMarketId)19217", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1736_storage" + "value": "t_struct(Market)9285_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1961_storage": { + "t_struct(FacetAddressAndPosition)9510_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1958, + "astId": 9507, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "facetAddress", "offset": 0, @@ -1816,7 +1845,7 @@ "type": "t_address" }, { - "astId": 1960, + "astId": 9509, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "functionSelectorPosition", "offset": 20, @@ -1826,12 +1855,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1967_storage": { + "t_struct(FacetFunctionSelectors)9516_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1964, + "astId": 9513, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "functionSelectors", "offset": 0, @@ -1839,7 +1868,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1966, + "astId": 9515, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "facetAddressPosition", "offset": 0, @@ -1849,12 +1878,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1736_storage": { + "t_struct(Market)9285_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1712, + "astId": 9261, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isListed", "offset": 0, @@ -1862,7 +1891,7 @@ "type": "t_bool" }, { - "astId": 1715, + "astId": 9264, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "collateralFactorMantissa", "offset": 0, @@ -1870,7 +1899,7 @@ "type": "t_uint256" }, { - "astId": 1720, + "astId": 9269, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "accountMembership", "offset": 0, @@ -1878,7 +1907,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1723, + "astId": 9272, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isVenus", "offset": 0, @@ -1886,7 +1915,7 @@ "type": "t_bool" }, { - "astId": 1726, + "astId": 9275, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "liquidationThresholdMantissa", "offset": 0, @@ -1894,7 +1923,7 @@ "type": "t_uint256" }, { - "astId": 1729, + "astId": 9278, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -1902,7 +1931,7 @@ "type": "t_uint256" }, { - "astId": 1732, + "astId": 9281, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "poolId", "offset": 0, @@ -1910,7 +1939,7 @@ "type": "t_uint96" }, { - "astId": 1735, + "astId": 9284, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isBorrowAllowed", "offset": 12, @@ -1920,12 +1949,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)2023_storage": { + "t_struct(PoolData)9572_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 2012, + "astId": 9561, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "label", "offset": 0, @@ -1933,7 +1962,7 @@ "type": "t_string_storage" }, { - "astId": 2016, + "astId": 9565, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "vTokens", "offset": 0, @@ -1941,7 +1970,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 2019, + "astId": 9568, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isActive", "offset": 0, @@ -1949,7 +1978,7 @@ "type": "t_bool" }, { - "astId": 2022, + "astId": 9571, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "allowCorePoolFallback", "offset": 1, @@ -1959,12 +1988,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1775_storage": { + "t_struct(VenusMarketState)9324_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1771, + "astId": 9320, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "index", "offset": 0, @@ -1972,7 +2001,7 @@ "type": "t_uint224" }, { - "astId": 1774, + "astId": 9323, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "block", "offset": 28, @@ -2002,7 +2031,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11427": { + "t_userDefinedValueType(PoolMarketId)19217": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bscmainnet/VaiUnitroller_Implementation.json b/deployments/bscmainnet/VaiUnitroller_Implementation.json index 1f346505f..e2d756898 100644 --- a/deployments/bscmainnet/VaiUnitroller_Implementation.json +++ b/deployments/bscmainnet/VaiUnitroller_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0xFD754b21F5dbbf6eb282911Cc0112cbF88190767", + "address": "0x8A7d8589A597619A7842d3BC284b9a5a276FaE56", "abi": [ { "anonymous": false, @@ -1091,28 +1091,28 @@ "type": "function" } ], - "transactionHash": "0xd82d68ef335d6bff23bdcb1fa7acaf016d76838130197b59c807fc1c111aef66", + "transactionHash": "0xa19ab2ee27a2ca59995b05480ddd301826d44daa440e1c948ccc4c7e0434b66e", "receipt": { "to": null, - "from": "0x7Bf1Fe2C42E79dbA813Bf5026B7720935a55ec5f", - "contractAddress": "0xFD754b21F5dbbf6eb282911Cc0112cbF88190767", - "transactionIndex": 140, - "gasUsed": "3658121", + "from": "0x9b0A3EAE7f174937d31745B710BbeA68e9D1BEf7", + "contractAddress": "0x8A7d8589A597619A7842d3BC284b9a5a276FaE56", + "transactionIndex": 30, + "gasUsed": "3762818", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xe469ae344ad5d620da0d2f67899ac89cb24cfce11b33c15d2a4c7a0758b32ad8", - "transactionHash": "0xd82d68ef335d6bff23bdcb1fa7acaf016d76838130197b59c807fc1c111aef66", + "blockHash": "0x3ea5f914b92492751e7c24ff517e3ca3bb229d74153eda369d7878f80a1f4e6e", + "transactionHash": "0xa19ab2ee27a2ca59995b05480ddd301826d44daa440e1c948ccc4c7e0434b66e", "logs": [], - "blockNumber": 70341354, - "cumulativeGasUsed": "24135035", + "blockNumber": 95562281, + "cumulativeGasUsed": "7929750", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "41a54ebccf0ff87cc6775f85f59eb745", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"LiquidateVAI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeAmount\",\"type\":\"uint256\"}],\"name\":\"MintFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"previousMintEnabledOnlyForPrimeHolder\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newMintEnabledOnlyForPrimeHolder\",\"type\":\"bool\"}],\"name\":\"MintOnlyForPrimeHolder\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mintVAIAmount\",\"type\":\"uint256\"}],\"name\":\"MintVAI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"NewAccessControl\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"oldComptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"newComptroller\",\"type\":\"address\"}],\"name\":\"NewComptroller\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPrime\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPrime\",\"type\":\"address\"}],\"name\":\"NewPrime\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"}],\"name\":\"NewTreasuryAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"}],\"name\":\"NewTreasuryGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldTreasuryPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"NewTreasuryPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBaseRateMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBaseRateMantissa\",\"type\":\"uint256\"}],\"name\":\"NewVAIBaseRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFloatRateMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFlatRateMantissa\",\"type\":\"uint256\"}],\"name\":\"NewVAIFloatRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMintCap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMintCap\",\"type\":\"uint256\"}],\"name\":\"NewVAIMintCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldReceiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newReceiver\",\"type\":\"address\"}],\"name\":\"NewVAIReceiver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldVaiToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newVaiToken\",\"type\":\"address\"}],\"name\":\"NewVaiToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayVAIAmount\",\"type\":\"uint256\"}],\"name\":\"RepayVAI\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_ID\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_VAI_MINT_INDEX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VAIUnitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"comptroller_\",\"type\":\"address\"}],\"name\":\"_setComptroller\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"_setTreasuryData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControl\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accrueVAIInterest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRateMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptroller\",\"outputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"floatRateMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"getMintableVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"getVAICalculateRepayAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"getVAIMinterInterestIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVAIRepayAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIRepayRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIRepayRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isVenusVAIInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"contract VTokenInterface\",\"name\":\"vTokenCollateral\",\"type\":\"address\"}],\"name\":\"liquidateVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintCap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintEnabledOnlyForPrimeHolder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"mintVAIAmount\",\"type\":\"uint256\"}],\"name\":\"mintVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"pastVAIInterest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingVAIControllerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"receiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repayVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repayVAIBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"setAccessControl\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBaseRateMantissa\",\"type\":\"uint256\"}],\"name\":\"setBaseRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFloatRateMantissa\",\"type\":\"uint256\"}],\"name\":\"setFloatRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_mintCap\",\"type\":\"uint256\"}],\"name\":\"setMintCap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"prime_\",\"type\":\"address\"}],\"name\":\"setPrimeToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newReceiver\",\"type\":\"address\"}],\"name\":\"setReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vai_\",\"type\":\"address\"}],\"name\":\"setVAIToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"toggleOnlyPrimeHolderMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiControllerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusVAIMinterIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setComptroller(address)\":{\"details\":\"Admin function to set a new comptroller\",\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setTreasuryData(address,address,uint256)\":{\"params\":{\"newTreasuryAddress\":\"New Treasury Address\",\"newTreasuryGuardian\":\"New Treasury Guardian address\",\"newTreasuryPercent\":\"New fee percentage for minting VAI that is sent to the treasury\"}},\"getMintableVAI(address)\":{\"params\":{\"minter\":\"The account to check mintable VAI\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\",\"_1\":\"Mintable amount (with 18 decimals)\"}},\"getVAIAddress()\":{\"returns\":{\"_0\":\"The address of VAI\"}},\"getVAICalculateRepayAmount(address,uint256)\":{\"params\":{\"borrower\":\"The address of the VAI borrower\",\"repayAmount\":\"The amount of VAI being returned\"},\"returns\":{\"_0\":\"Amount of VAI to be burned\",\"_1\":\"Amount of VAI the user needs to pay in current interest\",\"_2\":\"Amount of VAI the user needs to pay in past interest\"}},\"getVAIMinterInterestIndex(address)\":{\"params\":{\"minter\":\"Address of VAI minter\"},\"returns\":{\"_0\":\"uint256 Returns the interest rate index for a minter\"}},\"getVAIRepayAmount(address)\":{\"params\":{\"account\":\"The address of the VAI borrower\"},\"returns\":{\"_0\":\"(uint256) The total amount of VAI the user needs to repay\"}},\"getVAIRepayRate()\":{\"returns\":{\"_0\":\"uint256 Yearly VAI interest rate\"}},\"getVAIRepayRatePerBlock()\":{\"returns\":{\"_0\":\"uint256 Interest rate per bock\"}},\"liquidateVAI(address,uint256,address)\":{\"params\":{\"borrower\":\"The borrower of vai to be liquidated\",\"repayAmount\":\"The amount of the underlying borrowed asset to repay\",\"vTokenCollateral\":\"The market in which to seize collateral from the borrower\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"mintVAI(uint256)\":{\"details\":\"If the Comptroller address is not set, minting is a no-op and the function returns the success code.\",\"params\":{\"mintVAIAmount\":\"The amount of the VAI to be minted.\"},\"returns\":{\"_0\":\"0 on success, otherwise an error code\"}},\"repayVAI(uint256)\":{\"details\":\"If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\",\"params\":{\"amount\":\"The amount of VAI to be repaid.\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"repayVAIBehalf(address,uint256)\":{\"details\":\"If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\",\"params\":{\"amount\":\"The amount of VAI to be repaid.\",\"borrower\":\"The account to repay the debt for.\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"setAccessControl(address)\":{\"details\":\"Admin function to set the access control address\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"}},\"setBaseRate(uint256)\":{\"params\":{\"newBaseRateMantissa\":\"the base rate multiplied by 10**18\"}},\"setFloatRate(uint256)\":{\"params\":{\"newFloatRateMantissa\":\"the VAI float rate multiplied by 10**18\"}},\"setMintCap(uint256)\":{\"params\":{\"_mintCap\":\"the amount of VAI that can be minted\"}},\"setPrimeToken(address)\":{\"params\":{\"prime_\":\"The new address of the prime token contract\"}},\"setReceiver(address)\":{\"params\":{\"newReceiver\":\"the address of the VAI fee receiver\"}},\"setVAIToken(address)\":{\"params\":{\"vai_\":\"The new address of the VAI token contract\"}},\"toggleOnlyPrimeHolderMint()\":{\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}}},\"title\":\"VAI Comptroller\",\"version\":1},\"userdoc\":{\"events\":{\"LiquidateVAI(address,address,uint256,address,uint256)\":{\"notice\":\"Event emitted when a borrow is liquidated\"},\"MintFee(address,uint256)\":{\"notice\":\"Event emitted when VAIs are minted and fee are transferred\"},\"MintOnlyForPrimeHolder(bool,bool)\":{\"notice\":\"Emitted when mint for prime holder is changed\"},\"MintVAI(address,uint256)\":{\"notice\":\"Event emitted when VAI is minted\"},\"NewAccessControl(address,address)\":{\"notice\":\"Emitted when access control address is changed by admin\"},\"NewComptroller(address,address)\":{\"notice\":\"Emitted when Comptroller is changed\"},\"NewPrime(address,address)\":{\"notice\":\"Emitted when Prime is changed\"},\"NewTreasuryAddress(address,address)\":{\"notice\":\"Emitted when treasury address is changed\"},\"NewTreasuryGuardian(address,address)\":{\"notice\":\"Emitted when treasury guardian is changed\"},\"NewTreasuryPercent(uint256,uint256)\":{\"notice\":\"Emitted when treasury percent is changed\"},\"NewVAIBaseRate(uint256,uint256)\":{\"notice\":\"Emiitted when VAI base rate is changed\"},\"NewVAIFloatRate(uint256,uint256)\":{\"notice\":\"Emiitted when VAI float rate is changed\"},\"NewVAIMintCap(uint256,uint256)\":{\"notice\":\"Emiitted when VAI mint cap is changed\"},\"NewVAIReceiver(address,address)\":{\"notice\":\"Emiitted when VAI receiver address is changed\"},\"NewVaiToken(address,address)\":{\"notice\":\"Emitted when VAI token address is changed by admin\"},\"RepayVAI(address,address,uint256)\":{\"notice\":\"Event emitted when VAI is repaid\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_ID()\":{\"notice\":\"poolId for core Pool\"},\"INITIAL_VAI_MINT_INDEX()\":{\"notice\":\"Initial index used in interest computations\"},\"_setComptroller(address)\":{\"notice\":\"Sets a new comptroller\"},\"_setTreasuryData(address,address,uint256)\":{\"notice\":\"Update treasury data\"},\"accessControl()\":{\"notice\":\"Access control manager address\"},\"accrueVAIInterest()\":{\"notice\":\"Accrue interest on outstanding minted VAI\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"baseRateMantissa()\":{\"notice\":\"The base rate for stability fee\"},\"floatRateMantissa()\":{\"notice\":\"The float rate for stability fee\"},\"getMintableVAI(address)\":{\"notice\":\"Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\"},\"getVAIAddress()\":{\"notice\":\"Return the address of the VAI token\"},\"getVAICalculateRepayAmount(address,uint256)\":{\"notice\":\"Calculate how much VAI the user needs to repay\"},\"getVAIMinterInterestIndex(address)\":{\"notice\":\"Get the last updated interest index for a VAI Minter\"},\"getVAIRepayAmount(address)\":{\"notice\":\"Get the current total VAI a user needs to repay\"},\"getVAIRepayRate()\":{\"notice\":\"Gets yearly VAI interest rate based on the VAI price\"},\"getVAIRepayRatePerBlock()\":{\"notice\":\"Get interest rate per block\"},\"isVenusVAIInitialized()\":{\"notice\":\"The Venus VAI state initialized\"},\"liquidateVAI(address,uint256,address)\":{\"notice\":\"The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\"},\"mintCap()\":{\"notice\":\"VAI mint cap\"},\"mintEnabledOnlyForPrimeHolder()\":{\"notice\":\"Tracks if minting is enabled only for prime token holders. Only used if prime is set\"},\"mintVAI(uint256)\":{\"notice\":\"The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance. The amount minted must be less than the user's Account Liquidity and the mint vai limit.\"},\"pastVAIInterest(address)\":{\"notice\":\"Tracks the amount of mintedVAI of a user that represents the accrued interest\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingVAIControllerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"prime()\":{\"notice\":\"The address of the prime contract. It can be a ZERO address\"},\"receiver()\":{\"notice\":\"The address for VAI interest receiver\"},\"repayVAI(uint256)\":{\"notice\":\"The repay function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Before repaying VAI, users must first approve VAIController to access their VAI balance.\"},\"repayVAIBehalf(address,uint256)\":{\"notice\":\"The repay on behalf function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower). Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\"},\"setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"setBaseRate(uint256)\":{\"notice\":\"Set VAI borrow base rate\"},\"setFloatRate(uint256)\":{\"notice\":\"Set VAI borrow float rate\"},\"setMintCap(uint256)\":{\"notice\":\"Set VAI mint cap\"},\"setPrimeToken(address)\":{\"notice\":\"Set the prime token contract address\"},\"setReceiver(address)\":{\"notice\":\"Set VAI stability fee receiver address\"},\"setVAIToken(address)\":{\"notice\":\"Set the VAI token contract address\"},\"toggleOnlyPrimeHolderMint()\":{\"notice\":\"Toggle mint only for prime holder\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"vaiControllerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"vaiMintIndex()\":{\"notice\":\"Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\"},\"venusVAIMinterIndex(address)\":{\"notice\":\"The Venus VAI minter index as of the last time they accrued XVS\"},\"venusVAIState()\":{\"notice\":\"The Venus VAI state\"}},\"notice\":\"This is the implementation contract for the VAIUnitroller proxy\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Tokens/VAI/VAIController.sol\":\"VAIController\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0xb8de7a0684411bc301a5a4a3411656c712a7f94668b3ec617ec27b37cf6cd0ea\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/IVAI.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-or-later\\n// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico\\n\\npragma solidity 0.8.25;\\n\\ninterface IVAI {\\n // --- Auth ---\\n function wards(address) external view returns (uint256);\\n function rely(address guy) external;\\n function deny(address guy) external;\\n\\n // --- BEP20 Data ---\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function version() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint256);\\n\\n function balanceOf(address) external view returns (uint256);\\n function allowance(address, address) external view returns (uint256);\\n function nonces(address) external view returns (uint256);\\n\\n event Approval(address indexed src, address indexed guy, uint256 wad);\\n event Transfer(address indexed src, address indexed dst, uint256 wad);\\n\\n // --- EIP712 niceties ---\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n // bytes32 public constant PERMIT_TYPEHASH = keccak256(\\\"Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)\\\");\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n // --- Token ---\\n function transfer(address dst, uint256 wad) external returns (bool);\\n function transferFrom(address src, address dst, uint256 wad) external returns (bool);\\n function mint(address usr, uint256 wad) external;\\n function burn(address usr, uint256 wad) external;\\n function approve(address usr, uint256 wad) external returns (bool);\\n\\n // --- Alias ---\\n function push(address usr, uint256 wad) external;\\n function pull(address usr, uint256 wad) external;\\n function move(address src, address dst, uint256 wad) external;\\n\\n // --- Approve by signature ---\\n function permit(\\n address holder,\\n address spender,\\n uint256 nonce,\\n uint256 expiry,\\n bool allowed,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0x9d7c391c50cdd8ddadd030694e1fd9ee3456861bc0cca2f2a28a714c6470d0b3\",\"license\":\"AGPL-3.0-or-later\"},\"contracts/Tokens/VAI/VAIController.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { VAIControllerErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { VToken } from \\\"../VTokens/VToken.sol\\\";\\nimport { VAIUnitroller } from \\\"./VAIUnitroller.sol\\\";\\nimport { VAIControllerInterface } from \\\"./VAIControllerInterface.sol\\\";\\nimport { IVAI } from \\\"./IVAI.sol\\\";\\nimport { IPrime } from \\\"../Prime/IPrime.sol\\\";\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\nimport { VAIControllerStorageG4 } from \\\"./VAIControllerStorage.sol\\\";\\n\\n/**\\n * @title VAI Comptroller\\n * @author Venus\\n * @notice This is the implementation contract for the VAIUnitroller proxy\\n */\\ncontract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAIControllerErrorReporter, Exponential {\\n /// @notice Initial index used in interest computations\\n uint256 public constant INITIAL_VAI_MINT_INDEX = 1e18;\\n\\n /// poolId for core Pool\\n uint96 public constant CORE_POOL_ID = 0;\\n\\n /// @notice Emitted when Comptroller is changed\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /// @notice Emitted when mint for prime holder is changed\\n event MintOnlyForPrimeHolder(bool previousMintEnabledOnlyForPrimeHolder, bool newMintEnabledOnlyForPrimeHolder);\\n\\n /// @notice Emitted when Prime is changed\\n event NewPrime(address oldPrime, address newPrime);\\n\\n /// @notice Event emitted when VAI is minted\\n event MintVAI(address minter, uint256 mintVAIAmount);\\n\\n /// @notice Event emitted when VAI is repaid\\n event RepayVAI(address payer, address borrower, uint256 repayVAIAmount);\\n\\n /// @notice Event emitted when a borrow is liquidated\\n event LiquidateVAI(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n address vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /// @notice Emitted when treasury guardian is changed\\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\\n\\n /// @notice Emitted when treasury address is changed\\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\\n\\n /// @notice Emitted when treasury percent is changed\\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\\n\\n /// @notice Event emitted when VAIs are minted and fee are transferred\\n event MintFee(address minter, uint256 feeAmount);\\n\\n /// @notice Emiitted when VAI base rate is changed\\n event NewVAIBaseRate(uint256 oldBaseRateMantissa, uint256 newBaseRateMantissa);\\n\\n /// @notice Emiitted when VAI float rate is changed\\n event NewVAIFloatRate(uint256 oldFloatRateMantissa, uint256 newFlatRateMantissa);\\n\\n /// @notice Emiitted when VAI receiver address is changed\\n event NewVAIReceiver(address oldReceiver, address newReceiver);\\n\\n /// @notice Emiitted when VAI mint cap is changed\\n event NewVAIMintCap(uint256 oldMintCap, uint256 newMintCap);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /// @notice Emitted when VAI token address is changed by admin\\n event NewVaiToken(address oldVaiToken, address newVaiToken);\\n\\n function initialize() external onlyAdmin {\\n require(vaiMintIndex == 0, \\\"already initialized\\\");\\n\\n vaiMintIndex = INITIAL_VAI_MINT_INDEX;\\n accrualBlockNumber = getBlockNumber();\\n mintCap = type(uint256).max;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n function _become(VAIUnitroller unitroller) external {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance.\\n * The amount minted must be less than the user's Account Liquidity and the mint vai limit.\\n * @dev If the Comptroller address is not set, minting is a no-op and the function returns the success code.\\n * @param mintVAIAmount The amount of the VAI to be minted.\\n * @return 0 on success, otherwise an error code\\n */\\n // solhint-disable-next-line code-complexity\\n function mintVAI(uint256 mintVAIAmount) external nonReentrant returns (uint256) {\\n if (address(comptroller) == address(0)) {\\n return uint256(Error.NO_ERROR);\\n }\\n\\n require(comptroller.userPoolId(msg.sender) == CORE_POOL_ID, \\\"VAI mint only allowed in the core Pool\\\");\\n\\n _ensureNonzeroAmount(mintVAIAmount);\\n _ensureNotPaused();\\n accrueVAIInterest();\\n\\n uint256 err;\\n address minter = msg.sender;\\n address _vai = vai;\\n uint256 vaiTotalSupply = IVAI(_vai).totalSupply();\\n\\n uint256 vaiNewTotalSupply = add_(vaiTotalSupply, mintVAIAmount);\\n require(vaiNewTotalSupply <= mintCap, \\\"mint cap reached\\\");\\n\\n uint256 accountMintableVAI;\\n (err, accountMintableVAI) = getMintableVAI(minter);\\n require(err == uint256(Error.NO_ERROR), \\\"could not compute mintable amount\\\");\\n\\n // check that user have sufficient mintableVAI balance\\n require(mintVAIAmount <= accountMintableVAI, \\\"minting more than allowed\\\");\\n\\n // Calculate the minted balance based on interest index\\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\\n\\n if (totalMintedVAI > 0) {\\n uint256 repayAmount = getVAIRepayAmount(minter);\\n uint256 remainedAmount = sub_(repayAmount, totalMintedVAI);\\n pastVAIInterest[minter] = add_(pastVAIInterest[minter], remainedAmount);\\n totalMintedVAI = repayAmount;\\n }\\n\\n uint256 accountMintVAINew = add_(totalMintedVAI, mintVAIAmount);\\n err = comptroller.setMintedVAIOf(minter, accountMintVAINew);\\n require(err == uint256(Error.NO_ERROR), \\\"comptroller rejection\\\");\\n\\n uint256 remainedAmount;\\n if (treasuryPercent != 0) {\\n uint256 feeAmount = div_(mul_(mintVAIAmount, treasuryPercent), 1e18);\\n remainedAmount = sub_(mintVAIAmount, feeAmount);\\n IVAI(_vai).mint(treasuryAddress, feeAmount);\\n\\n emit MintFee(minter, feeAmount);\\n } else {\\n remainedAmount = mintVAIAmount;\\n }\\n\\n IVAI(_vai).mint(minter, remainedAmount);\\n vaiMinterInterestIndex[minter] = vaiMintIndex;\\n\\n emit MintVAI(minter, remainedAmount);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice The repay function transfers VAI interest into the protocol and burns the rest,\\n * reducing the borrower's borrow balance. Before repaying VAI, users must first approve\\n * VAIController to access their VAI balance.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAI(uint256 amount) external nonReentrant returns (uint256, uint256) {\\n return _repayVAI(msg.sender, amount);\\n }\\n\\n /**\\n * @notice The repay on behalf function transfers VAI interest into the protocol and burns the rest,\\n * reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower).\\n * Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param borrower The account to repay the debt for.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAIBehalf(address borrower, uint256 amount) external nonReentrant returns (uint256, uint256) {\\n _ensureNonzeroAddress(borrower);\\n return _repayVAI(borrower, amount);\\n }\\n\\n /**\\n * @dev Checks the parameters and the protocol state, accrues interest, and invokes repayVAIFresh.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param borrower The account to repay the debt for.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function _repayVAI(address borrower, uint256 amount) internal returns (uint256, uint256) {\\n if (address(comptroller) == address(0)) {\\n return (0, 0);\\n }\\n _ensureNonzeroAmount(amount);\\n _ensureNotPaused();\\n\\n accrueVAIInterest();\\n return repayVAIFresh(msg.sender, borrower, amount);\\n }\\n\\n /**\\n * @dev Repay VAI, expecting interest to be accrued\\n * @dev Borrowed VAIs are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the VAI\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of VAI being repaid\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAIFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256, uint256) {\\n (uint256 burn, uint256 partOfCurrentInterest, uint256 partOfPastInterest) = getVAICalculateRepayAmount(\\n borrower,\\n repayAmount\\n );\\n\\n IVAI _vai = IVAI(vai);\\n _vai.burn(payer, burn);\\n bool success = _vai.transferFrom(payer, receiver, partOfCurrentInterest);\\n require(success == true, \\\"failed to transfer VAI fee\\\");\\n\\n uint256 vaiBalanceBorrower = comptroller.mintedVAIs(borrower);\\n\\n uint256 accountVAINew = sub_(sub_(vaiBalanceBorrower, burn), partOfPastInterest);\\n pastVAIInterest[borrower] = sub_(pastVAIInterest[borrower], partOfPastInterest);\\n\\n uint256 error = comptroller.setMintedVAIOf(borrower, accountVAINew);\\n // We have to revert upon error since side-effects already happened at this point\\n require(error == uint256(Error.NO_ERROR), \\\"comptroller rejection\\\");\\n\\n uint256 repaidAmount = add_(burn, partOfCurrentInterest);\\n emit RepayVAI(payer, borrower, repaidAmount);\\n\\n return (uint256(Error.NO_ERROR), repaidAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of vai to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external nonReentrant returns (uint256, uint256) {\\n _ensureNotPaused();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != uint256(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateVAIFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateVAIFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral by repay borrowers VAI.\\n * The collateral seized is transferred to the liquidator.\\n * @dev If the Comptroller address is not set, liquidation is a no-op and the function returns the success code.\\n * @param liquidator The address repaying the VAI and seizing collateral\\n * @param borrower The borrower of this VAI to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the VAI to repay\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function liquidateVAIFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint256, uint256) {\\n if (address(comptroller) != address(0)) {\\n accrueVAIInterest();\\n\\n /* Fail if liquidate not allowed */\\n uint256 allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n //if (vTokenCollateral.accrualBlockNumber() != accrualBlockNumber) {\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayVAI fails */\\n (uint256 repayBorrowError, uint256 actualRepayAmount) = repayVAIFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint256(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateVAICalculateSeizeTokens(\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(\\n amountSeizeError == uint256(Error.NO_ERROR),\\n \\\"VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\"\\n );\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"VAI_LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n uint256 seizeError;\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint256(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateVAI(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint256(Error.NO_ERROR), actualRepayAmount);\\n }\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new comptroller\\n * @dev Admin function to set a new comptroller\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface comptroller_) external returns (uint256) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n comptroller = comptroller_;\\n emit NewComptroller(oldComptroller, comptroller_);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the prime token contract address\\n * @param prime_ The new address of the prime token contract\\n */\\n function setPrimeToken(address prime_) external onlyAdmin {\\n emit NewPrime(prime, prime_);\\n prime = prime_;\\n }\\n\\n /**\\n * @notice Set the VAI token contract address\\n * @param vai_ The new address of the VAI token contract\\n */\\n function setVAIToken(address vai_) external onlyAdmin {\\n emit NewVaiToken(vai, vai_);\\n vai = vai_;\\n }\\n\\n /**\\n * @notice Toggle mint only for prime holder\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function toggleOnlyPrimeHolderMint() external returns (uint256) {\\n _ensureAllowed(\\\"toggleOnlyPrimeHolderMint()\\\");\\n\\n if (!mintEnabledOnlyForPrimeHolder && prime == address(0)) {\\n return uint256(Error.REJECTION);\\n }\\n\\n emit MintOnlyForPrimeHolder(mintEnabledOnlyForPrimeHolder, !mintEnabledOnlyForPrimeHolder);\\n mintEnabledOnlyForPrimeHolder = !mintEnabledOnlyForPrimeHolder;\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account total supply balance.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountAmountLocalVars {\\n uint256 oErr;\\n MathError mErr;\\n uint256 sumSupply;\\n uint256 marketSupply;\\n uint256 sumBorrowPlusEffects;\\n uint256 vTokenBalance;\\n uint256 borrowBalance;\\n uint256 exchangeRateMantissa;\\n uint256 oraclePriceMantissa;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate\\n * If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\\n * @param minter The account to check mintable VAI\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\\n * @return Mintable amount (with 18 decimals)\\n */\\n // solhint-disable-next-line code-complexity\\n function getMintableVAI(address minter) public view returns (uint256, uint256) {\\n if (mintEnabledOnlyForPrimeHolder && !IPrime(prime).isUserPrimeHolder(minter)) {\\n return (uint256(Error.REJECTION), 0);\\n }\\n\\n ResilientOracleInterface oracle = comptroller.oracle();\\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\\n\\n AccountAmountLocalVars memory vars; // Holds all our calculation results\\n\\n uint256 accountMintableVAI;\\n uint256 i;\\n\\n /**\\n * We use this formula to calculate mintable VAI amount.\\n * totalSupplyAmount * VAIMintRate - (totalBorrowAmount + mintedVAIOf)\\n */\\n uint256 marketsCount = enteredMarkets.length;\\n for (i = 0; i < marketsCount; i++) {\\n (vars.oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = enteredMarkets[i]\\n .getAccountSnapshot(minter);\\n if (vars.oErr != 0) {\\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (uint256(Error.SNAPSHOT_ERROR), 0);\\n }\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(address(enteredMarkets[i]));\\n if (vars.oraclePriceMantissa == 0) {\\n return (uint256(Error.PRICE_ERROR), 0);\\n }\\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n\\n (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.oraclePrice);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n // marketSupply = tokensToDenom * vTokenBalance\\n (vars.mErr, vars.marketSupply) = mulScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (, uint256 collateralFactorMantissa, , , , , ) = comptroller.markets(address(enteredMarkets[i]));\\n (vars.mErr, vars.marketSupply) = mulUInt(vars.marketSupply, collateralFactorMantissa);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, vars.marketSupply) = divUInt(vars.marketSupply, 1e18);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, vars.sumSupply) = addUInt(vars.sumSupply, vars.marketSupply);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\\n (vars.mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(\\n vars.oraclePrice,\\n vars.borrowBalance,\\n vars.sumBorrowPlusEffects\\n );\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n }\\n\\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\\n uint256 repayAmount = 0;\\n\\n if (totalMintedVAI > 0) {\\n repayAmount = getVAIRepayAmount(minter);\\n }\\n\\n (vars.mErr, vars.sumBorrowPlusEffects) = addUInt(vars.sumBorrowPlusEffects, repayAmount);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, accountMintableVAI) = mulUInt(vars.sumSupply, comptroller.vaiMintRate());\\n require(vars.mErr == MathError.NO_ERROR, \\\"VAI_MINT_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (vars.mErr, accountMintableVAI) = divUInt(accountMintableVAI, 10000);\\n require(vars.mErr == MathError.NO_ERROR, \\\"VAI_MINT_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (vars.mErr, accountMintableVAI) = subUInt(accountMintableVAI, vars.sumBorrowPlusEffects);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.REJECTION), 0);\\n }\\n\\n return (uint256(Error.NO_ERROR), accountMintableVAI);\\n }\\n\\n /**\\n * @notice Update treasury data\\n * @param newTreasuryGuardian New Treasury Guardian address\\n * @param newTreasuryAddress New Treasury Address\\n * @param newTreasuryPercent New fee percentage for minting VAI that is sent to the treasury\\n */\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256) {\\n // Check caller is admin\\n if (!(msg.sender == admin || msg.sender == treasuryGuardian)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_TREASURY_OWNER_CHECK);\\n }\\n\\n require(newTreasuryPercent < 1e18, \\\"treasury percent cap overflow\\\");\\n\\n address oldTreasuryGuardian = treasuryGuardian;\\n address oldTreasuryAddress = treasuryAddress;\\n uint256 oldTreasuryPercent = treasuryPercent;\\n\\n treasuryGuardian = newTreasuryGuardian;\\n treasuryAddress = newTreasuryAddress;\\n treasuryPercent = newTreasuryPercent;\\n\\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Gets yearly VAI interest rate based on the VAI price\\n * @return uint256 Yearly VAI interest rate\\n */\\n function getVAIRepayRate() public view returns (uint256) {\\n ResilientOracleInterface oracle = comptroller.oracle();\\n MathError mErr;\\n\\n if (baseRateMantissa > 0) {\\n if (floatRateMantissa > 0) {\\n uint256 oraclePrice = oracle.getUnderlyingPrice(getVAIAddress());\\n if (1e18 > oraclePrice) {\\n uint256 delta;\\n uint256 rate;\\n\\n (mErr, delta) = subUInt(1e18, oraclePrice);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = mulUInt(delta, floatRateMantissa);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = divUInt(delta, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, rate) = addUInt(delta, baseRateMantissa);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n return rate;\\n } else {\\n return baseRateMantissa;\\n }\\n } else {\\n return baseRateMantissa;\\n }\\n } else {\\n return 0;\\n }\\n }\\n\\n /**\\n * @notice Get interest rate per block\\n * @return uint256 Interest rate per bock\\n */\\n function getVAIRepayRatePerBlock() public view returns (uint256) {\\n uint256 yearlyRate = getVAIRepayRate();\\n\\n MathError mErr;\\n uint256 rate;\\n\\n (mErr, rate) = divUInt(yearlyRate, getBlocksPerYear());\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Get the last updated interest index for a VAI Minter\\n * @param minter Address of VAI minter\\n * @return uint256 Returns the interest rate index for a minter\\n */\\n function getVAIMinterInterestIndex(address minter) public view returns (uint256) {\\n uint256 storedIndex = vaiMinterInterestIndex[minter];\\n // If the user minted VAI before the stability fee was introduced, accrue\\n // starting from stability fee launch\\n if (storedIndex == 0) {\\n return INITIAL_VAI_MINT_INDEX;\\n }\\n return storedIndex;\\n }\\n\\n /**\\n * @notice Get the current total VAI a user needs to repay\\n * @param account The address of the VAI borrower\\n * @return (uint256) The total amount of VAI the user needs to repay\\n */\\n function getVAIRepayAmount(address account) public view returns (uint256) {\\n MathError mErr;\\n uint256 delta;\\n\\n uint256 amount = comptroller.mintedVAIs(account);\\n uint256 interest = pastVAIInterest[account];\\n uint256 totalMintedVAI;\\n uint256 newInterest;\\n\\n (mErr, totalMintedVAI) = subUInt(amount, interest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = subUInt(vaiMintIndex, getVAIMinterInterestIndex(account));\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, newInterest) = mulUInt(delta, totalMintedVAI);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, newInterest) = divUInt(newInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, amount) = addUInt(amount, newInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n return amount;\\n }\\n\\n /**\\n * @notice Calculate how much VAI the user needs to repay\\n * @param borrower The address of the VAI borrower\\n * @param repayAmount The amount of VAI being returned\\n * @return Amount of VAI to be burned\\n * @return Amount of VAI the user needs to pay in current interest\\n * @return Amount of VAI the user needs to pay in past interest\\n */\\n function getVAICalculateRepayAmount(\\n address borrower,\\n uint256 repayAmount\\n ) public view returns (uint256, uint256, uint256) {\\n MathError mErr;\\n uint256 totalRepayAmount = getVAIRepayAmount(borrower);\\n uint256 currentInterest;\\n\\n (mErr, currentInterest) = subUInt(totalRepayAmount, comptroller.mintedVAIs(borrower));\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, currentInterest) = addUInt(pastVAIInterest[borrower], currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n uint256 burn;\\n uint256 partOfCurrentInterest = currentInterest;\\n uint256 partOfPastInterest = pastVAIInterest[borrower];\\n\\n if (repayAmount >= totalRepayAmount) {\\n (mErr, burn) = subUInt(totalRepayAmount, currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n } else {\\n uint256 delta;\\n\\n (mErr, delta) = mulUInt(repayAmount, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PART_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = divUInt(delta, totalRepayAmount);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PART_CALCULATION_FAILED\\\");\\n\\n uint256 totalMintedAmount;\\n (mErr, totalMintedAmount) = subUInt(totalRepayAmount, currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_MINTED_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, burn) = mulUInt(totalMintedAmount, delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, burn) = divUInt(burn, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfCurrentInterest) = mulUInt(currentInterest, delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfCurrentInterest) = divUInt(partOfCurrentInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfPastInterest) = mulUInt(pastVAIInterest[borrower], delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PAST_INTEREST_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfPastInterest) = divUInt(partOfPastInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PAST_INTEREST_CALCULATION_FAILED\\\");\\n }\\n\\n return (burn, partOfCurrentInterest, partOfPastInterest);\\n }\\n\\n /**\\n * @notice Accrue interest on outstanding minted VAI\\n */\\n function accrueVAIInterest() public {\\n MathError mErr;\\n uint256 delta;\\n\\n (mErr, delta) = mulUInt(getVAIRepayRatePerBlock(), getBlockNumber() - accrualBlockNumber);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_INTEREST_ACCRUE_FAILED\\\");\\n\\n (mErr, delta) = addUInt(delta, vaiMintIndex);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_INTEREST_ACCRUE_FAILED\\\");\\n\\n vaiMintIndex = delta;\\n accrualBlockNumber = getBlockNumber();\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlAddress New address for the access control\\n */\\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\\n _ensureNonzeroAddress(newAccessControlAddress);\\n\\n address oldAccessControlAddress = accessControl;\\n accessControl = newAccessControlAddress;\\n emit NewAccessControl(oldAccessControlAddress, accessControl);\\n }\\n\\n /**\\n * @notice Set VAI borrow base rate\\n * @param newBaseRateMantissa the base rate multiplied by 10**18\\n */\\n function setBaseRate(uint256 newBaseRateMantissa) external {\\n _ensureAllowed(\\\"setBaseRate(uint256)\\\");\\n\\n uint256 old = baseRateMantissa;\\n baseRateMantissa = newBaseRateMantissa;\\n emit NewVAIBaseRate(old, baseRateMantissa);\\n }\\n\\n /**\\n * @notice Set VAI borrow float rate\\n * @param newFloatRateMantissa the VAI float rate multiplied by 10**18\\n */\\n function setFloatRate(uint256 newFloatRateMantissa) external {\\n _ensureAllowed(\\\"setFloatRate(uint256)\\\");\\n\\n uint256 old = floatRateMantissa;\\n floatRateMantissa = newFloatRateMantissa;\\n emit NewVAIFloatRate(old, floatRateMantissa);\\n }\\n\\n /**\\n * @notice Set VAI stability fee receiver address\\n * @param newReceiver the address of the VAI fee receiver\\n */\\n function setReceiver(address newReceiver) external onlyAdmin {\\n _ensureNonzeroAddress(newReceiver);\\n\\n address old = receiver;\\n receiver = newReceiver;\\n emit NewVAIReceiver(old, newReceiver);\\n }\\n\\n /**\\n * @notice Set VAI mint cap\\n * @param _mintCap the amount of VAI that can be minted\\n */\\n function setMintCap(uint256 _mintCap) external {\\n _ensureAllowed(\\\"setMintCap(uint256)\\\");\\n\\n uint256 old = mintCap;\\n mintCap = _mintCap;\\n emit NewVAIMintCap(old, _mintCap);\\n }\\n\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n function getBlocksPerYear() public view virtual returns (uint256) {\\n return 70080000; //(24 * 60 * 60 * 365) / 0.45;\\n }\\n\\n /**\\n * @notice Return the address of the VAI token\\n * @return The address of VAI\\n */\\n function getVAIAddress() public view virtual returns (address) {\\n return vai;\\n }\\n\\n modifier onlyAdmin() {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n _;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n function _ensureAllowed(string memory functionSig) private view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /// @dev Reverts if the protocol is paused\\n function _ensureNotPaused() private view {\\n require(!comptroller.protocolPaused(), \\\"protocol is paused\\\");\\n }\\n\\n /// @dev Reverts if the passed address is zero\\n function _ensureNonzeroAddress(address someone) private pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @dev Reverts if the passed amount is zero\\n function _ensureNonzeroAmount(uint256 amount) private pure {\\n require(amount > 0, \\\"amount can't be zero\\\");\\n }\\n}\\n\",\"keccak256\":\"0xd206ef1c5dc5fad0d01005b8b237f0f4cc370475958f72381a42a89346b26872\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\n\\ncontract VAIUnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public vaiControllerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingVAIControllerImplementation;\\n}\\n\\ncontract VAIControllerStorageG1 is VAIUnitrollerAdminStorage {\\n ComptrollerInterface public comptroller;\\n\\n struct VenusVAIState {\\n /// @notice The last updated venusVAIMintIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice The Venus VAI state\\n VenusVAIState public venusVAIState;\\n\\n /// @notice The Venus VAI state initialized\\n bool public isVenusVAIInitialized;\\n\\n /// @notice The Venus VAI minter index as of the last time they accrued XVS\\n mapping(address => uint256) public venusVAIMinterIndex;\\n}\\n\\ncontract VAIControllerStorageG2 is VAIControllerStorageG1 {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n\\n /// @notice Guard variable for re-entrancy checks\\n bool internal _notEntered;\\n\\n /// @notice The base rate for stability fee\\n uint256 public baseRateMantissa;\\n\\n /// @notice The float rate for stability fee\\n uint256 public floatRateMantissa;\\n\\n /// @notice The address for VAI interest receiver\\n address public receiver;\\n\\n /// @notice Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\\n uint256 public vaiMintIndex;\\n\\n /// @notice Block number that interest was last accrued at\\n uint256 internal accrualBlockNumber;\\n\\n /// @notice Global vaiMintIndex as of the most recent balance-changing action for user\\n mapping(address => uint256) internal vaiMinterInterestIndex;\\n\\n /// @notice Tracks the amount of mintedVAI of a user that represents the accrued interest\\n mapping(address => uint256) public pastVAIInterest;\\n\\n /// @notice VAI mint cap\\n uint256 public mintCap;\\n\\n /// @notice Access control manager address\\n address public accessControl;\\n}\\n\\ncontract VAIControllerStorageG3 is VAIControllerStorageG2 {\\n /// @notice The address of the prime contract. It can be a ZERO address\\n address public prime;\\n\\n /// @notice Tracks if minting is enabled only for prime token holders. Only used if prime is set\\n bool public mintEnabledOnlyForPrimeHolder;\\n}\\n\\ncontract VAIControllerStorageG4 is VAIControllerStorageG3 {\\n /// @notice The address of the VAI token\\n address internal vai;\\n}\\n\",\"keccak256\":\"0x75295c0c9d1e5e7b8726b0d43c260975eb4d8d0b76325360c39723b996b95603\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIUnitroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { VAIControllerErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { VAIUnitrollerAdminStorage } from \\\"./VAIControllerStorage.sol\\\";\\n\\n/**\\n * @title VAI Unitroller\\n * @author Venus\\n * @notice This is the proxy contract for the VAIComptroller\\n */\\ncontract VAIUnitroller is VAIUnitrollerAdminStorage, VAIControllerErrorReporter {\\n /**\\n * @notice Emitted when pendingVAIControllerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingVAIControllerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint256) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingVAIControllerImplementation;\\n\\n pendingVAIControllerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint256) {\\n // Check caller is pendingImplementation\\n if (msg.sender != pendingVAIControllerImplementation) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = vaiControllerImplementation;\\n address oldPendingImplementation = pendingVAIControllerImplementation;\\n\\n vaiControllerImplementation = pendingVAIControllerImplementation;\\n\\n pendingVAIControllerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, vaiControllerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint256) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint256) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n fallback() external {\\n // delegate all other functions to current implementation\\n (bool success, ) = vaiControllerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize())\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize())\\n }\\n default {\\n return(free_mem_ptr, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe33306ad442bbfe51c50572f91005d98cb657649316ca29aa650fa679dbca86\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint vTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n if (cashPrior < totalReservesNew) {\\n _reduceReservesFresh(cashPrior);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintBelahfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, 1e18);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(address borrower, address payable receiver, uint borrowAmount) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // totalReserves - reduceAmount\\n uint totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModelV8 oldInterestRateModel;\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0x24ceb1a473f6e51ec1a7085b0a5b734c0104001bfddd3165b672e3ad2d5467d4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1409d08c6eb3181b2a62913e1c9457a57ce747c062dbf89d6aa568e316add079\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0xad8d795a0011f59304cae938f062a72a998710c01db94f9a813b4f2f00c9534b\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0xf03faf89ad2689a29f0d456c1add258bc09bcf484840170154a32e129500818e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506141218061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061028b575f3560e01c8063691e45ac11610161578063b49b1005116100ca578063d24febad11610084578063d24febad146105a1578063e44e6168146105b4578063ee1fa41e146105fa578063f20fd8f41461060e578063f7260d3e1461062d578063f851a44014610640575f80fd5b8063b49b100514610547578063b9ee87261461054f578063c32094c714610557578063c5f956af1461056a578063c7ee005e1461057d578063cbeb2b2814610590575f80fd5b806378c2f9221161011b57806378c2f922146104de5780637a37c5d0146104f15780638129fc1c14610510578063b06bb42614610518578063b2b481bc1461052b578063b2eafc3914610534575f80fd5b8063691e45ac1461046f5780636fe74a211461049d578063718da7ee146104b0578063741de148146104c357806375c3de43146104cd57806376c71ca1146104d5575f80fd5b80633785d1d6116102035780635ce73240116101bd5780635ce732401461040c5780635fe3b5671461041557806360c954ef1461042857806361b3311c146104455780636509795414610458578063657bdf9414610467575f80fd5b80633785d1d6146103a45780633b5a0a64146103b75780633b72fbef146103ca5780634070a0c9146103d35780634576b5db146103e65780634712ee7d146103f9575f80fd5b80631d08837b116102545780631d08837b146103265780631d504dc6146103395780631f040ff51461034c578063234f89771461035f57806324650602146103725780632678224714610391575f80fd5b80623b58841461028f57806304ef9d58146102bf57806311b3d5e7146102d657806313007d55146102fe57806319129e5a14610311575b5f80fd5b6002546102a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102c8600a5481565b6040519081526020016102b6565b6102e96102e4366004613ae9565b610652565b604080519283526020830191909152016102b6565b6014546102a2906001600160a01b031681565b61032461031f366004613b28565b61074d565b005b610324610334366004613b43565b6107e1565b610324610347366004613b28565b610854565b6102e961035a366004613b5a565b6109cd565b6102c861036d366004613b28565b610a2a565b6102c8610380366004613b28565b60076020525f908152604090205481565b6001546102a2906001600160a01b031681565b6102e96103b2366004613b28565b610a5f565b6103246103c5366004613b43565b611372565b6102c8600c5481565b6103246103e1366004613b43565b6113e6565b6102c86103f4366004613b28565b611458565b6102c8610407366004613b43565b6114dc565b6102c8600d5481565b6004546102a2906001600160a01b031681565b6006546104359060ff1681565b60405190151581526020016102b6565b610324610453366004613b28565b611ae0565b6102c8670de0b6b3a764000081565b6102c8611b72565b61048261047d366004613b5a565b611c4b565b604080519384526020840192909252908201526060016102b6565b6102e96104ab366004613b43565b6120e8565b6103246104be366004613b28565b61213a565b63042d56006102c8565b6102c86121c6565b6102c860135481565b6102c86104ec366004613b28565b612217565b6104f85f81565b6040516001600160601b0390911681526020016102b6565b6103246123fe565b6003546102a2906001600160a01b031681565b6102c8600f5481565b6008546102a2906001600160a01b031681565b610324612491565b6102c861258b565b610324610565366004613b28565b6127dc565b6009546102a2906001600160a01b031681565b6015546102a2906001600160a01b031681565b6016546001600160a01b03166102a2565b6102c86105af366004613b84565b61286e565b6005546105d6906001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016102b6565b60155461043590600160a01b900460ff1681565b6102c861061c366004613b28565b60126020525f908152604090205481565b600e546102a2906001600160a01b031681565b5f546102a2906001600160a01b031681565b600b545f90819060ff166106815760405162461bcd60e51b815260040161067890613bc2565b60405180910390fd5b600b805460ff19169055610693612a03565b5f836001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303815f875af11580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190613be6565b905080156107245761071981600681111561071257610712613bfd565b6008612ab0565b5f9250925050610736565b61073033878787612b27565b92509250505b600b805460ff191660011790559094909350915050565b5f546001600160a01b031633146107765760405162461bcd60e51b815260040161067890613c11565b61077f81613050565b601480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd491015b60405180910390a15050565b6108166040518060400160405280601481526020017373657442617365526174652875696e743235362960601b81525061309e565b600c80549082905560408051828152602081018490527fc84c32795e68685ec107b0e94ae126ef464095f342c7e2e0fec06a23d2e8677e91016107d5565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b49190613c39565b6001600160a01b0316336001600160a01b0316146109245760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610678565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610961573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109859190613be6565b156109ca5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610678565b50565b600b545f90819060ff166109f35760405162461bcd60e51b815260040161067890613bc2565b600b805460ff19169055610a0684613050565b610a10848461314b565b91509150600b805460ff1916600117905590939092509050565b6001600160a01b0381165f90815260116020526040812054808203610a595750670de0b6b3a764000092915050565b92915050565b6015545f908190600160a01b900460ff168015610ae55750601554604051630e3da90d60e21b81526001600160a01b038581166004830152909116906338f6a43490602401602060405180830381865afa158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae39190613c68565b155b15610af5576002935f9350915050565b5f60045f9054906101000a90046001600160a01b03166001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190613c39565b60048054604051632aff3bff60e21b81526001600160a01b03888116938201939093529293505f9291169063abfceffc906024015f60405180830381865afa158015610bb8573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bdf9190810190613ca0565b9050610be9613a43565b81515f9081905b808210156110b657848281518110610c0a57610c0a613d60565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038b811660048301529091169063c37f68e290602401608060405180830381865afa158015610c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613d74565b60e088015260c087015260a086015280855215610ca75760035b995f9950975050505050505050565b60405180602001604052808560e00151815250846101200181905250856001600160a01b031663fc57d4df868481518110610ce457610ce4613d60565b60200260200101516040518263ffffffff1660e01b8152600401610d1791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610d32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d569190613be6565b61010085018190525f03610d6b576004610c98565b604080516020810190915261010085015181526101408501819052610120850151610d9591613199565b856020018661016001829052826003811115610db357610db3613bfd565b6003811115610dc457610dc4613bfd565b9052505f905084602001516003811115610de057610de0613bfd565b14610dec576005610c98565b610dff8461016001518560a001516132a6565b6060860181905260208601826003811115610e1c57610e1c613bfd565b6003811115610e2d57610e2d613bfd565b9052505f905084602001516003811115610e4957610e49613bfd565b14610e55576005610c98565b60045485515f916001600160a01b031690638e8f294b90889086908110610e7e57610e7e613d60565b60200260200101516040518263ffffffff1660e01b8152600401610eb191906001600160a01b0391909116815260200190565b60e060405180830381865afa158015610ecc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef09190613dbd565b5050505050915050610f068560600151826132f3565b6060870181905260208701826003811115610f2357610f23613bfd565b6003811115610f3457610f34613bfd565b9052505f905085602001516003811115610f5057610f50613bfd565b14610f685760055b9a5f9a5098505050505050505050565b610f7e8560600151670de0b6b3a7640000613330565b6060870181905260208701826003811115610f9b57610f9b613bfd565b6003811115610fac57610fac613bfd565b9052505f905085602001516003811115610fc857610fc8613bfd565b14610fd4576005610f58565b610fe68560400151866060015161334f565b604087018190526020870182600381111561100357611003613bfd565b600381111561101457611014613bfd565b9052505f90508560200151600381111561103057611030613bfd565b1461103c576005610f58565b6110548561014001518660c001518760800151613372565b608087018190526020870182600381111561107157611071613bfd565b600381111561108257611082613bfd565b9052505f90508560200151600381111561109e5761109e613bfd565b146110aa576005610f58565b50600190910190610bf0565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611103573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111279190613be6565b90505f811561113c576111398b612217565b90505b61114a86608001518261334f565b608088018190526020880182600381111561116757611167613bfd565b600381111561117857611178613bfd565b9052505f90508660200151600381111561119457611194613bfd565b146111ad5760055b9b5f9b509950505050505050505050565b61122e866040015160045f9054906101000a90046001600160a01b03166001600160a01b031663bec04f726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611205573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112299190613be6565b6132f3565b8760200181975082600381111561124757611247613bfd565b600381111561125857611258613bfd565b9052505f90508660200151600381111561127457611274613bfd565b146112915760405162461bcd60e51b815260040161067890613e29565b61129d85612710613330565b876020018197508260038111156112b6576112b6613bfd565b60038111156112c7576112c7613bfd565b9052505f9050866020015160038111156112e3576112e3613bfd565b146113005760405162461bcd60e51b815260040161067890613e29565b61130e8587608001516133c9565b8760200181975082600381111561132757611327613bfd565b600381111561133857611338613bfd565b9052505f90508660200151600381111561135457611354613bfd565b1461136057600261119c565b5f9b949a509398505050505050505050565b6113a860405180604001604052806015815260200174736574466c6f6174526174652875696e743235362960581b81525061309e565b600d80549082905560408051828152602081018490527f546fb35dbbd92233aecc22b5a11a6791e5db7ec14f62e49cbac2a10c0437f56191016107d5565b61141a604051806040016040528060138152602001727365744d696e744361702875696e743235362960681b81525061309e565b601380549082905560408051828152602081018490527f43862b3eea2df8fce70329f3f84cbcad220f47a73be46c5e00df25165a6e169591016107d5565b5f80546001600160a01b0316331461147657610a5960016002612ab0565b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d910160405180910390a15f5b9392505050565b600b545f9060ff166115005760405162461bcd60e51b815260040161067890613bc2565b600b805460ff191690556004546001600160a01b031661152157505f611ace565b60048054604051637376909960e01b815233928101929092525f916001600160a01b0390911690637376909990602401602060405180830381865afa15801561156c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115909190613e6b565b6001600160601b0316146115f55760405162461bcd60e51b815260206004820152602660248201527f564149206d696e74206f6e6c7920616c6c6f77656420696e2074686520636f726044820152651948141bdbdb60d21b6064820152608401610678565b6115fe826133e9565b611606612a03565b61160e612491565b601654604080516318160ddd60e01b815290515f9233926001600160a01b0390911691849183916318160ddd916004808201926020929091908290030181865afa15801561165e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116829190613be6565b90505f61168f828861342f565b90506013548111156116d65760405162461bcd60e51b815260206004820152601060248201526f1b5a5b9d0818d85c081c995858da195960821b6044820152606401610678565b5f6116e085610a5f565b9096509050851561173d5760405162461bcd60e51b815260206004820152602160248201527f636f756c64206e6f7420636f6d70757465206d696e7461626c6520616d6f756e6044820152601d60fa1b6064820152608401610678565b8088111561178d5760405162461bcd60e51b815260206004820152601960248201527f6d696e74696e67206d6f7265207468616e20616c6c6f776564000000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b03888116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa1580156117da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117fe9190613be6565b9050801561185e575f61181087612217565b90505f61181d8284613464565b6001600160a01b0389165f90815260126020526040902054909150611842908261342f565b6001600160a01b0389165f908152601260205260409020555090505b5f611869828b61342f565b6004805460405163fd51a3ad60e01b81526001600160a01b038b81169382019390935260248101849052929350169063fd51a3ad906044016020604051808303815f875af11580156118bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118e19190613be6565b975087156119295760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f600a545f14611a09575f6119516119438d600a5461349d565b670de0b6b3a76400006134de565b905061195d8c82613464565b6009546040516340c10f1960e01b81526001600160a01b039182166004820152602481018490529193508916906340c10f19906044015f604051808303815f87803b1580156119aa575f80fd5b505af11580156119bc573d5f803e3d5ffd5b5050604080516001600160a01b038d168152602081018590527fb0715a6d41a37c1b0672c22c09a31a0642c1fb3f9efa2d5fd5c6d2d891ee78c6935001905060405180910390a150611a0c565b50895b6040516340c10f1960e01b81526001600160a01b038981166004830152602482018390528816906340c10f19906044015f604051808303815f87803b158015611a53575f80fd5b505af1158015611a65573d5f803e3d5ffd5b5050600f546001600160a01b038b165f818152601160209081526040918290209390935580519182529181018590527e2e68ab1600fc5e7290e2ceaa79e2f86b4dbaca84a48421e167e0b40409218a935001905060405180910390a15f99505050505050505050505b600b805460ff19166001179055919050565b5f546001600160a01b03163314611b095760405162461bcd60e51b815260040161067890613c11565b601654604080516001600160a01b03928316815291831660208301527fe45150fb0a88e2274ecbca05ddde9925dd64b6e126ae0fa23ee2d42e668a49d3910160405180910390a1601680546001600160a01b0319166001600160a01b0392909216919091179055565b5f611bb16040518060400160405280601b81526020017f746f67676c654f6e6c795072696d65486f6c6465724d696e742829000000000081525061309e565b601554600160a01b900460ff16158015611bd457506015546001600160a01b0316155b15611bdf5750600290565b60155460408051600160a01b90920460ff16158015835260208301527f8efa7b6021d602e0cdef814b7435609ee40deb2a0352ca676d10045750516a5f910160405180910390a16015805460ff60a01b198116600160a01b9182900460ff16159091021790555f905090565b5f805f805f611c5987612217565b600480546040516315e3f14f60e11b81526001600160a01b038b8116938201939093529293505f92611cd69285921690632bc7e29e90602401602060405180830381865afa158015611cad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd19190613be6565b6133c9565b90935090505f836003811115611cee57611cee613bfd565b14611d0b5760405162461bcd60e51b815260040161067890613e84565b6001600160a01b0388165f90815260126020526040902054611d2d908261334f565b90935090505f836003811115611d4557611d45613bfd565b14611d625760405162461bcd60e51b815260040161067890613e84565b6001600160a01b0388165f908152601260205260408120548290848a10611dc757611d8d85856133c9565b90965092505f866003811115611da557611da5613bfd565b14611dc25760405162461bcd60e51b815260040161067890613e84565b6120d7565b5f611dda8b670de0b6b3a76400006132f3565b90975090505f876003811115611df257611df2613bfd565b14611e3f5760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b611e498187613330565b90975090505f876003811115611e6157611e61613bfd565b14611eae5760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b5f611eb987876133c9565b90985090505f886003811115611ed157611ed1613bfd565b14611f2a5760405162461bcd60e51b8152602060048201526024808201527f5641495f4d494e5445445f414d4f554e545f43414c43554c4154494f4e5f46416044820152631253115160e21b6064820152608401610678565b611f3481836132f3565b90985094505f886003811115611f4c57611f4c613bfd565b14611f695760405162461bcd60e51b815260040161067890613e84565b611f7b85670de0b6b3a7640000613330565b90985094505f886003811115611f9357611f93613bfd565b14611fb05760405162461bcd60e51b815260040161067890613e84565b611fba86836132f3565b90985093505f886003811115611fd257611fd2613bfd565b14611fef5760405162461bcd60e51b815260040161067890613ec6565b61200184670de0b6b3a7640000613330565b90985093505f88600381111561201957612019613bfd565b146120365760405162461bcd60e51b815260040161067890613ec6565b6001600160a01b038d165f9081526012602052604090205461205890836132f3565b90985092505f88600381111561207057612070613bfd565b1461208d5760405162461bcd60e51b815260040161067890613f14565b61209f83670de0b6b3a7640000613330565b90985092505f8860038111156120b7576120b7613bfd565b146120d45760405162461bcd60e51b815260040161067890613f14565b50505b919750955093505050509250925092565b600b545f90819060ff1661210e5760405162461bcd60e51b815260040161067890613bc2565b600b805460ff19169055612122338461314b565b91509150600b805460ff191660011790559092909150565b5f546001600160a01b031633146121635760405162461bcd60e51b815260040161067890613c11565b61216c81613050565b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f4df62dd7d9cc4f480a167c19c616ae5d5bb40db6d0c2bc66dba57068225f00d891016107d5565b5f806121d061258b565b90505f806121e28363042d5600613330565b90925090505f8260038111156121fa576121fa613bfd565b146114d55760405162461bcd60e51b815260040161067890613f58565b600480546040516315e3f14f60e11b81526001600160a01b03848116938201939093525f9283928392839290911690632bc7e29e90602401602060405180830381865afa15801561226a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061228e9190613be6565b6001600160a01b0386165f90815260126020526040812054919250806122b484846133c9565b90965091505f8660038111156122cc576122cc613bfd565b146122e95760405162461bcd60e51b815260040161067890613f99565b6122f8600f54611cd18a610a2a565b90965094505f86600381111561231057612310613bfd565b1461232d5760405162461bcd60e51b815260040161067890613f99565b61233785836132f3565b90965090505f86600381111561234f5761234f613bfd565b1461236c5760405162461bcd60e51b815260040161067890613f99565b61237e81670de0b6b3a7640000613330565b90965090505f86600381111561239657612396613bfd565b146123b35760405162461bcd60e51b815260040161067890613f99565b6123bd848261334f565b90965093505f8660038111156123d5576123d5613bfd565b146123f25760405162461bcd60e51b815260040161067890613f99565b50919695505050505050565b5f546001600160a01b031633146124275760405162461bcd60e51b815260040161067890613c11565b600f541561246d5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610678565b670de0b6b3a7640000600f55436010555f19601355600b805460ff19166001179055565b5f806124ab61249e6121c6565b6010546112299043613ff6565b90925090505f8260038111156124c3576124c3613bfd565b146125105760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b61251c81600f5461334f565b90925090505f82600381111561253457612534613bfd565b146125815760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b600f555043601055565b60048054604080516307dc0d1d60e41b815290515f9384936001600160a01b031692637dc0d1d092818301926020928290030181865afa1580156125d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125f59190613c39565b90505f80600c5411156127d457600d54156127ca575f826001600160a01b031663fc57d4df61262c6016546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561266e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126929190613be6565b905080670de0b6b3a764000011156127bf575f806126b8670de0b6b3a7640000846133c9565b90945091505f8460038111156126d0576126d0613bfd565b146126ed5760405162461bcd60e51b815260040161067890613f58565b6126f982600d546132f3565b90945091505f84600381111561271157612711613bfd565b1461272e5760405162461bcd60e51b815260040161067890613f58565b61274082670de0b6b3a7640000613330565b90945091505f84600381111561275857612758613bfd565b146127755760405162461bcd60e51b815260040161067890613f58565b61278182600c5461334f565b90945090505f84600381111561279957612799613bfd565b146127b65760405162461bcd60e51b815260040161067890613f58565b95945050505050565b600c54935050505090565b600c549250505090565b5f9250505090565b5f546001600160a01b031633146128055760405162461bcd60e51b815260040161067890613c11565b601554604080516001600160a01b03928316815291831660208301527ffb26401242c61b503dd09c29da64a5d4f451549f574b882a40bcdc64ee68b83c910160405180910390a1601580546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b031633148061289157506008546001600160a01b031633145b6128a8576128a160016017612ab0565b90506114d5565b670de0b6b3a764000082106128ff5760405162461bcd60e51b815260206004820152601d60248201527f74726561737572792070657263656e7420636170206f766572666c6f770000006044820152606401610678565b6008805460098054600a80546001600160a01b03198086166001600160a01b038c81169182179098559084168a8816179094559087905560408051948616808652602086019490945292949091169290917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e8910160405180910390a1604080516001600160a01b038085168252881660208201527f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac910160405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a1505f9695505050505050565b600480546040805163084bf5ab60e31b815290516001600160a01b039092169263425fad589282820192602092908290030181865afa158015612a48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a6c9190613c68565b15612aae5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610678565b565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836006811115612ae457612ae4613bfd565b836017811115612af657612af6613bfd565b6040805192835260208301919091525f9082015260600160405180910390a18260068111156114d5576114d5613bfd565b6004545f9081906001600160a01b03161561304757612b44612491565b60048054604051632fe3f38f60e11b815230928101929092526001600160a01b03858116602484015288811660448401528781166064840152608483018790525f92911690635fc7e71e9060a4016020604051808303815f875af1158015612bae573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd29190613be6565b90508015612bf257612be76002600a83613510565b5f9250925050613047565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c2f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c539190613be6565b14612c6457612be760026009612ab0565b866001600160a01b0316866001600160a01b031603612c8957612be76002600f612ab0565b845f03612c9c57612be76002600d612ab0565b5f198503612cb057612be76002600c612ab0565b5f80612cbd89898961358f565b90925090508115612cf157612ce4826006811115612cdd57612cdd613bfd565b6010612ab0565b5f94509450505050613047565b6004805460405163a78dc77560e01b81526001600160a01b0389811693820193909352602481018490525f928392169063a78dc775906044016040805180830381865afa158015612d44573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d689190614009565b90925090508115612de15760405162461bcd60e51b815260206004820152603760248201527f5641495f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c60448201527f4154455f414d4f554e545f5345495a455f4641494c45440000000000000000006064820152608401610678565b6040516370a0823160e01b81526001600160a01b038b811660048301528291908a16906370a0823190602401602060405180830381865afa158015612e28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e4c9190613be6565b1015612e9a5760405162461bcd60e51b815260206004820152601c60248201527f5641495f4c49515549444154455f5345495a455f544f4f5f4d554348000000006044820152606401610678565b60405163b2a02ff160e01b81526001600160a01b038c811660048301528b81166024830152604482018390525f91908a169063b2a02ff1906064016020604051808303815f875af1158015612ef1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f159190613be6565b90508015612f5c5760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610678565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f42d401f96718a0c42e5cea8108973f0022677b7e2e5f4ee19851b2de7a0394e79181900360a00190a1600480546040516347ef3b3b60e01b815230928101929092526001600160a01b038b811660248401528e811660448401528d811660648401526084830187905260a4830185905216906347ef3b3b9060c4015f604051808303815f87803b15801561301e575f80fd5b505af1158015613030573d5f803e3d5ffd5b505f925061303c915050565b975092955050505050505b94509492505050565b6001600160a01b0381166109ca5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610678565b6014546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906130d09033908590600401614059565b602060405180830381865afa1580156130eb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061310f9190613c68565b6109ca5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610678565b6004545f9081906001600160a01b031661316957505f905080613192565b613172836133e9565b61317a612a03565b613182612491565b61318d33858561358f565b915091505b9250929050565b5f6131af60405180602001604052805f81525090565b5f806131c1865f0151865f01516132f3565b90925090505f8260038111156131d9576131d9613bfd565b146131f7575060408051602081019091525f81529092509050613192565b5f8061321561320f6002670de0b6b3a764000061407c565b8461334f565b90925090505f82600381111561322d5761322d613bfd565b1461324f578160405180602001604052805f8152509550955050505050613192565b5f8061326383670de0b6b3a7640000613330565b90925090505f82600381111561327b5761327b613bfd565b146132885761328861409b565b60408051602081019091529081525f9a909950975050505050505050565b5f805f806132b486866138d5565b90925090505f8260038111156132cc576132cc613bfd565b146132dc575091505f9050613192565b5f6132e68261394a565b9350935050509250929050565b5f80835f0361330657505f905080613192565b83830283613314868361407c565b146133265760025f9250925050613192565b5f92509050613192565b5f80825f036133445750600190505f613192565b5f61318d848661407c565b5f80838301848110613365575f92509050613192565b60025f9250925050613192565b5f805f8061338087876138d5565b90925090505f82600381111561339857613398613bfd565b146133a8575091505f90506133c1565b6133ba6133b48261394a565b8661334f565b9350935050505b935093915050565b5f808383116133de57505f9050818303613192565b50600390505f613192565b5f81116109ca5760405162461bcd60e51b8152602060048201526014602482015273616d6f756e742063616e2774206265207a65726f60601b6044820152606401610678565b5f6114d58383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250613961565b5f6114d58383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061399a565b5f6114d583836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506139c8565b5f6114d583836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613a18565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084600681111561354457613544613bfd565b84601781111561355657613556613bfd565b604080519283526020830191909152810184905260600160405180910390a183600681111561358757613587613bfd565b949350505050565b5f805f805f61359e8787611c4b565b601654604051632770a7eb60e21b81526001600160a01b038d811660048301526024820186905294975092955090935091909116908190639dc29fac906044015f604051808303815f87803b1580156135f5575f80fd5b505af1158015613607573d5f803e3d5ffd5b5050600e546040516323b872dd60e01b81526001600160a01b038d811660048301529182166024820152604481018790525f935090841691506323b872dd906064016020604051808303815f875af1158015613665573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136899190613c68565b90506001811515146136dd5760405162461bcd60e51b815260206004820152601a60248201527f6661696c656420746f207472616e7366657220564149206665650000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa15801561372a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061374e9190613be6565b90505f61376461375e8389613464565b86613464565b6001600160a01b038c165f908152601260205260409020549091506137899086613464565b6001600160a01b03808d165f818152601260205260408082209490945560048054945163fd51a3ad60e01b81529081019290925260248201859052929091169063fd51a3ad906044016020604051808303815f875af11580156137ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138129190613be6565b9050801561385a5760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f613865898961342f565b90507f1db858e6f7e1a0d5e92c10c6507d42b3dabfe0a4867fe90c5a14d9963662ef7e8e8e836040516138b9939291906001600160a01b039384168152919092166020820152604081019190915260600190565b60405180910390a15f9e909d509b505050505050505050505050565b5f6138eb60405180602001604052805f81525090565b5f806138fa865f0151866132f3565b90925090505f82600381111561391257613912613bfd565b14613930575060408051602081019091525f81529092509050613192565b60408051602081019091529081525f969095509350505050565b80515f90610a5990670de0b6b3a76400009061407c565b5f8061396d84866140af565b905082858210156139915760405162461bcd60e51b815260040161067891906140c2565b50949350505050565b5f81848411156139bd5760405162461bcd60e51b815260040161067891906140c2565b506135878385613ff6565b5f8315806139d4575082155b156139e057505f6114d5565b5f6139eb84866140d4565b9050836139f8868361407c565b1483906139915760405162461bcd60e51b815260040161067891906140c2565b5f8183613a385760405162461bcd60e51b815260040161067891906140c2565b50613587838561407c565b6040805161018081019091525f808252602082019081526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001613a9c60405180602001604052805f81525090565b8152602001613ab660405180602001604052805f81525090565b8152602001613ad060405180602001604052805f81525090565b905290565b6001600160a01b03811681146109ca575f80fd5b5f805f60608486031215613afb575f80fd5b8335613b0681613ad5565b9250602084013591506040840135613b1d81613ad5565b809150509250925092565b5f60208284031215613b38575f80fd5b81356114d581613ad5565b5f60208284031215613b53575f80fd5b5035919050565b5f8060408385031215613b6b575f80fd5b8235613b7681613ad5565b946020939093013593505050565b5f805f60608486031215613b96575f80fd5b8335613ba181613ad5565b92506020840135613bb181613ad5565b929592945050506040919091013590565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b5f60208284031215613bf6575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b6020808252600e908201526d37b7363c9030b236b4b71031b0b760911b604082015260600190565b5f60208284031215613c49575f80fd5b81516114d581613ad5565b80518015158114613c63575f80fd5b919050565b5f60208284031215613c78575f80fd5b6114d582613c54565b634e487b7160e01b5f52604160045260245ffd5b8051613c6381613ad5565b5f6020808385031215613cb1575f80fd5b825167ffffffffffffffff80821115613cc8575f80fd5b818501915085601f830112613cdb575f80fd5b815181811115613ced57613ced613c81565b8060051b604051601f19603f83011681018181108582111715613d1257613d12613c81565b604052918252848201925083810185019188831115613d2f575f80fd5b938501935b82851015613d5457613d4585613c95565b84529385019392850192613d34565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215613d87575f80fd5b505082516020840151604085015160609095015191969095509092509050565b80516001600160601b0381168114613c63575f80fd5b5f805f805f805f60e0888a031215613dd3575f80fd5b613ddc88613c54565b965060208801519550613df160408901613c54565b94506060880151935060808801519250613e0d60a08901613da7565b9150613e1b60c08901613c54565b905092959891949750929550565b60208082526022908201527f5641495f4d494e545f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b5f60208284031215613e7b575f80fd5b6114d582613da7565b60208082526022908201527f5641495f4255524e5f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b6020808252602e908201527f5641495f43555252454e545f494e5445524553545f414d4f554e545f43414c4360408201526d155310551253d397d1905253115160921b606082015260800190565b60208082526024908201527f5641495f504153545f494e5445524553545f43414c43554c4154494f4e5f46416040820152631253115160e21b606082015260800190565b60208082526021908201527f5641495f52455041595f524154455f43414c43554c4154494f4e5f4641494c456040820152601160fa1b606082015260800190565b60208082526029908201527f5641495f544f54414c5f52455041595f414d4f554e545f43414c43554c41544960408201526813d397d1905253115160ba1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a5957610a59613fe2565b5f806040838503121561401a575f80fd5b505080516020909101519092909150565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f906135879083018461402b565b5f8261409657634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52600160045260245ffd5b80820180821115610a5957610a59613fe2565b602081525f6114d5602083018461402b565b8082028115828204841417610a5957610a59613fe256fea26469706673582212200ef15b6b7b15c1ccd6e2253973c2553bb634afc0c39fd76759cbd01b1c70c89264736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061028b575f3560e01c8063691e45ac11610161578063b49b1005116100ca578063d24febad11610084578063d24febad146105a1578063e44e6168146105b4578063ee1fa41e146105fa578063f20fd8f41461060e578063f7260d3e1461062d578063f851a44014610640575f80fd5b8063b49b100514610547578063b9ee87261461054f578063c32094c714610557578063c5f956af1461056a578063c7ee005e1461057d578063cbeb2b2814610590575f80fd5b806378c2f9221161011b57806378c2f922146104de5780637a37c5d0146104f15780638129fc1c14610510578063b06bb42614610518578063b2b481bc1461052b578063b2eafc3914610534575f80fd5b8063691e45ac1461046f5780636fe74a211461049d578063718da7ee146104b0578063741de148146104c357806375c3de43146104cd57806376c71ca1146104d5575f80fd5b80633785d1d6116102035780635ce73240116101bd5780635ce732401461040c5780635fe3b5671461041557806360c954ef1461042857806361b3311c146104455780636509795414610458578063657bdf9414610467575f80fd5b80633785d1d6146103a45780633b5a0a64146103b75780633b72fbef146103ca5780634070a0c9146103d35780634576b5db146103e65780634712ee7d146103f9575f80fd5b80631d08837b116102545780631d08837b146103265780631d504dc6146103395780631f040ff51461034c578063234f89771461035f57806324650602146103725780632678224714610391575f80fd5b80623b58841461028f57806304ef9d58146102bf57806311b3d5e7146102d657806313007d55146102fe57806319129e5a14610311575b5f80fd5b6002546102a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102c8600a5481565b6040519081526020016102b6565b6102e96102e4366004613ae9565b610652565b604080519283526020830191909152016102b6565b6014546102a2906001600160a01b031681565b61032461031f366004613b28565b61074d565b005b610324610334366004613b43565b6107e1565b610324610347366004613b28565b610854565b6102e961035a366004613b5a565b6109cd565b6102c861036d366004613b28565b610a2a565b6102c8610380366004613b28565b60076020525f908152604090205481565b6001546102a2906001600160a01b031681565b6102e96103b2366004613b28565b610a5f565b6103246103c5366004613b43565b611372565b6102c8600c5481565b6103246103e1366004613b43565b6113e6565b6102c86103f4366004613b28565b611458565b6102c8610407366004613b43565b6114dc565b6102c8600d5481565b6004546102a2906001600160a01b031681565b6006546104359060ff1681565b60405190151581526020016102b6565b610324610453366004613b28565b611ae0565b6102c8670de0b6b3a764000081565b6102c8611b72565b61048261047d366004613b5a565b611c4b565b604080519384526020840192909252908201526060016102b6565b6102e96104ab366004613b43565b6120e8565b6103246104be366004613b28565b61213a565b63042d56006102c8565b6102c86121c6565b6102c860135481565b6102c86104ec366004613b28565b612217565b6104f85f81565b6040516001600160601b0390911681526020016102b6565b6103246123fe565b6003546102a2906001600160a01b031681565b6102c8600f5481565b6008546102a2906001600160a01b031681565b610324612491565b6102c861258b565b610324610565366004613b28565b6127dc565b6009546102a2906001600160a01b031681565b6015546102a2906001600160a01b031681565b6016546001600160a01b03166102a2565b6102c86105af366004613b84565b61286e565b6005546105d6906001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016102b6565b60155461043590600160a01b900460ff1681565b6102c861061c366004613b28565b60126020525f908152604090205481565b600e546102a2906001600160a01b031681565b5f546102a2906001600160a01b031681565b600b545f90819060ff166106815760405162461bcd60e51b815260040161067890613bc2565b60405180910390fd5b600b805460ff19169055610693612a03565b5f836001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303815f875af11580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190613be6565b905080156107245761071981600681111561071257610712613bfd565b6008612ab0565b5f9250925050610736565b61073033878787612b27565b92509250505b600b805460ff191660011790559094909350915050565b5f546001600160a01b031633146107765760405162461bcd60e51b815260040161067890613c11565b61077f81613050565b601480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd491015b60405180910390a15050565b6108166040518060400160405280601481526020017373657442617365526174652875696e743235362960601b81525061309e565b600c80549082905560408051828152602081018490527fc84c32795e68685ec107b0e94ae126ef464095f342c7e2e0fec06a23d2e8677e91016107d5565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b49190613c39565b6001600160a01b0316336001600160a01b0316146109245760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610678565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610961573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109859190613be6565b156109ca5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610678565b50565b600b545f90819060ff166109f35760405162461bcd60e51b815260040161067890613bc2565b600b805460ff19169055610a0684613050565b610a10848461314b565b91509150600b805460ff1916600117905590939092509050565b6001600160a01b0381165f90815260116020526040812054808203610a595750670de0b6b3a764000092915050565b92915050565b6015545f908190600160a01b900460ff168015610ae55750601554604051630e3da90d60e21b81526001600160a01b038581166004830152909116906338f6a43490602401602060405180830381865afa158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae39190613c68565b155b15610af5576002935f9350915050565b5f60045f9054906101000a90046001600160a01b03166001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190613c39565b60048054604051632aff3bff60e21b81526001600160a01b03888116938201939093529293505f9291169063abfceffc906024015f60405180830381865afa158015610bb8573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bdf9190810190613ca0565b9050610be9613a43565b81515f9081905b808210156110b657848281518110610c0a57610c0a613d60565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038b811660048301529091169063c37f68e290602401608060405180830381865afa158015610c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613d74565b60e088015260c087015260a086015280855215610ca75760035b995f9950975050505050505050565b60405180602001604052808560e00151815250846101200181905250856001600160a01b031663fc57d4df868481518110610ce457610ce4613d60565b60200260200101516040518263ffffffff1660e01b8152600401610d1791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610d32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d569190613be6565b61010085018190525f03610d6b576004610c98565b604080516020810190915261010085015181526101408501819052610120850151610d9591613199565b856020018661016001829052826003811115610db357610db3613bfd565b6003811115610dc457610dc4613bfd565b9052505f905084602001516003811115610de057610de0613bfd565b14610dec576005610c98565b610dff8461016001518560a001516132a6565b6060860181905260208601826003811115610e1c57610e1c613bfd565b6003811115610e2d57610e2d613bfd565b9052505f905084602001516003811115610e4957610e49613bfd565b14610e55576005610c98565b60045485515f916001600160a01b031690638e8f294b90889086908110610e7e57610e7e613d60565b60200260200101516040518263ffffffff1660e01b8152600401610eb191906001600160a01b0391909116815260200190565b60e060405180830381865afa158015610ecc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef09190613dbd565b5050505050915050610f068560600151826132f3565b6060870181905260208701826003811115610f2357610f23613bfd565b6003811115610f3457610f34613bfd565b9052505f905085602001516003811115610f5057610f50613bfd565b14610f685760055b9a5f9a5098505050505050505050565b610f7e8560600151670de0b6b3a7640000613330565b6060870181905260208701826003811115610f9b57610f9b613bfd565b6003811115610fac57610fac613bfd565b9052505f905085602001516003811115610fc857610fc8613bfd565b14610fd4576005610f58565b610fe68560400151866060015161334f565b604087018190526020870182600381111561100357611003613bfd565b600381111561101457611014613bfd565b9052505f90508560200151600381111561103057611030613bfd565b1461103c576005610f58565b6110548561014001518660c001518760800151613372565b608087018190526020870182600381111561107157611071613bfd565b600381111561108257611082613bfd565b9052505f90508560200151600381111561109e5761109e613bfd565b146110aa576005610f58565b50600190910190610bf0565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611103573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111279190613be6565b90505f811561113c576111398b612217565b90505b61114a86608001518261334f565b608088018190526020880182600381111561116757611167613bfd565b600381111561117857611178613bfd565b9052505f90508660200151600381111561119457611194613bfd565b146111ad5760055b9b5f9b509950505050505050505050565b61122e866040015160045f9054906101000a90046001600160a01b03166001600160a01b031663bec04f726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611205573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112299190613be6565b6132f3565b8760200181975082600381111561124757611247613bfd565b600381111561125857611258613bfd565b9052505f90508660200151600381111561127457611274613bfd565b146112915760405162461bcd60e51b815260040161067890613e29565b61129d85612710613330565b876020018197508260038111156112b6576112b6613bfd565b60038111156112c7576112c7613bfd565b9052505f9050866020015160038111156112e3576112e3613bfd565b146113005760405162461bcd60e51b815260040161067890613e29565b61130e8587608001516133c9565b8760200181975082600381111561132757611327613bfd565b600381111561133857611338613bfd565b9052505f90508660200151600381111561135457611354613bfd565b1461136057600261119c565b5f9b949a509398505050505050505050565b6113a860405180604001604052806015815260200174736574466c6f6174526174652875696e743235362960581b81525061309e565b600d80549082905560408051828152602081018490527f546fb35dbbd92233aecc22b5a11a6791e5db7ec14f62e49cbac2a10c0437f56191016107d5565b61141a604051806040016040528060138152602001727365744d696e744361702875696e743235362960681b81525061309e565b601380549082905560408051828152602081018490527f43862b3eea2df8fce70329f3f84cbcad220f47a73be46c5e00df25165a6e169591016107d5565b5f80546001600160a01b0316331461147657610a5960016002612ab0565b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d910160405180910390a15f5b9392505050565b600b545f9060ff166115005760405162461bcd60e51b815260040161067890613bc2565b600b805460ff191690556004546001600160a01b031661152157505f611ace565b60048054604051637376909960e01b815233928101929092525f916001600160a01b0390911690637376909990602401602060405180830381865afa15801561156c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115909190613e6b565b6001600160601b0316146115f55760405162461bcd60e51b815260206004820152602660248201527f564149206d696e74206f6e6c7920616c6c6f77656420696e2074686520636f726044820152651948141bdbdb60d21b6064820152608401610678565b6115fe826133e9565b611606612a03565b61160e612491565b601654604080516318160ddd60e01b815290515f9233926001600160a01b0390911691849183916318160ddd916004808201926020929091908290030181865afa15801561165e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116829190613be6565b90505f61168f828861342f565b90506013548111156116d65760405162461bcd60e51b815260206004820152601060248201526f1b5a5b9d0818d85c081c995858da195960821b6044820152606401610678565b5f6116e085610a5f565b9096509050851561173d5760405162461bcd60e51b815260206004820152602160248201527f636f756c64206e6f7420636f6d70757465206d696e7461626c6520616d6f756e6044820152601d60fa1b6064820152608401610678565b8088111561178d5760405162461bcd60e51b815260206004820152601960248201527f6d696e74696e67206d6f7265207468616e20616c6c6f776564000000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b03888116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa1580156117da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117fe9190613be6565b9050801561185e575f61181087612217565b90505f61181d8284613464565b6001600160a01b0389165f90815260126020526040902054909150611842908261342f565b6001600160a01b0389165f908152601260205260409020555090505b5f611869828b61342f565b6004805460405163fd51a3ad60e01b81526001600160a01b038b81169382019390935260248101849052929350169063fd51a3ad906044016020604051808303815f875af11580156118bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118e19190613be6565b975087156119295760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f600a545f14611a09575f6119516119438d600a5461349d565b670de0b6b3a76400006134de565b905061195d8c82613464565b6009546040516340c10f1960e01b81526001600160a01b039182166004820152602481018490529193508916906340c10f19906044015f604051808303815f87803b1580156119aa575f80fd5b505af11580156119bc573d5f803e3d5ffd5b5050604080516001600160a01b038d168152602081018590527fb0715a6d41a37c1b0672c22c09a31a0642c1fb3f9efa2d5fd5c6d2d891ee78c6935001905060405180910390a150611a0c565b50895b6040516340c10f1960e01b81526001600160a01b038981166004830152602482018390528816906340c10f19906044015f604051808303815f87803b158015611a53575f80fd5b505af1158015611a65573d5f803e3d5ffd5b5050600f546001600160a01b038b165f818152601160209081526040918290209390935580519182529181018590527e2e68ab1600fc5e7290e2ceaa79e2f86b4dbaca84a48421e167e0b40409218a935001905060405180910390a15f99505050505050505050505b600b805460ff19166001179055919050565b5f546001600160a01b03163314611b095760405162461bcd60e51b815260040161067890613c11565b601654604080516001600160a01b03928316815291831660208301527fe45150fb0a88e2274ecbca05ddde9925dd64b6e126ae0fa23ee2d42e668a49d3910160405180910390a1601680546001600160a01b0319166001600160a01b0392909216919091179055565b5f611bb16040518060400160405280601b81526020017f746f67676c654f6e6c795072696d65486f6c6465724d696e742829000000000081525061309e565b601554600160a01b900460ff16158015611bd457506015546001600160a01b0316155b15611bdf5750600290565b60155460408051600160a01b90920460ff16158015835260208301527f8efa7b6021d602e0cdef814b7435609ee40deb2a0352ca676d10045750516a5f910160405180910390a16015805460ff60a01b198116600160a01b9182900460ff16159091021790555f905090565b5f805f805f611c5987612217565b600480546040516315e3f14f60e11b81526001600160a01b038b8116938201939093529293505f92611cd69285921690632bc7e29e90602401602060405180830381865afa158015611cad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd19190613be6565b6133c9565b90935090505f836003811115611cee57611cee613bfd565b14611d0b5760405162461bcd60e51b815260040161067890613e84565b6001600160a01b0388165f90815260126020526040902054611d2d908261334f565b90935090505f836003811115611d4557611d45613bfd565b14611d625760405162461bcd60e51b815260040161067890613e84565b6001600160a01b0388165f908152601260205260408120548290848a10611dc757611d8d85856133c9565b90965092505f866003811115611da557611da5613bfd565b14611dc25760405162461bcd60e51b815260040161067890613e84565b6120d7565b5f611dda8b670de0b6b3a76400006132f3565b90975090505f876003811115611df257611df2613bfd565b14611e3f5760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b611e498187613330565b90975090505f876003811115611e6157611e61613bfd565b14611eae5760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b5f611eb987876133c9565b90985090505f886003811115611ed157611ed1613bfd565b14611f2a5760405162461bcd60e51b8152602060048201526024808201527f5641495f4d494e5445445f414d4f554e545f43414c43554c4154494f4e5f46416044820152631253115160e21b6064820152608401610678565b611f3481836132f3565b90985094505f886003811115611f4c57611f4c613bfd565b14611f695760405162461bcd60e51b815260040161067890613e84565b611f7b85670de0b6b3a7640000613330565b90985094505f886003811115611f9357611f93613bfd565b14611fb05760405162461bcd60e51b815260040161067890613e84565b611fba86836132f3565b90985093505f886003811115611fd257611fd2613bfd565b14611fef5760405162461bcd60e51b815260040161067890613ec6565b61200184670de0b6b3a7640000613330565b90985093505f88600381111561201957612019613bfd565b146120365760405162461bcd60e51b815260040161067890613ec6565b6001600160a01b038d165f9081526012602052604090205461205890836132f3565b90985092505f88600381111561207057612070613bfd565b1461208d5760405162461bcd60e51b815260040161067890613f14565b61209f83670de0b6b3a7640000613330565b90985092505f8860038111156120b7576120b7613bfd565b146120d45760405162461bcd60e51b815260040161067890613f14565b50505b919750955093505050509250925092565b600b545f90819060ff1661210e5760405162461bcd60e51b815260040161067890613bc2565b600b805460ff19169055612122338461314b565b91509150600b805460ff191660011790559092909150565b5f546001600160a01b031633146121635760405162461bcd60e51b815260040161067890613c11565b61216c81613050565b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f4df62dd7d9cc4f480a167c19c616ae5d5bb40db6d0c2bc66dba57068225f00d891016107d5565b5f806121d061258b565b90505f806121e28363042d5600613330565b90925090505f8260038111156121fa576121fa613bfd565b146114d55760405162461bcd60e51b815260040161067890613f58565b600480546040516315e3f14f60e11b81526001600160a01b03848116938201939093525f9283928392839290911690632bc7e29e90602401602060405180830381865afa15801561226a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061228e9190613be6565b6001600160a01b0386165f90815260126020526040812054919250806122b484846133c9565b90965091505f8660038111156122cc576122cc613bfd565b146122e95760405162461bcd60e51b815260040161067890613f99565b6122f8600f54611cd18a610a2a565b90965094505f86600381111561231057612310613bfd565b1461232d5760405162461bcd60e51b815260040161067890613f99565b61233785836132f3565b90965090505f86600381111561234f5761234f613bfd565b1461236c5760405162461bcd60e51b815260040161067890613f99565b61237e81670de0b6b3a7640000613330565b90965090505f86600381111561239657612396613bfd565b146123b35760405162461bcd60e51b815260040161067890613f99565b6123bd848261334f565b90965093505f8660038111156123d5576123d5613bfd565b146123f25760405162461bcd60e51b815260040161067890613f99565b50919695505050505050565b5f546001600160a01b031633146124275760405162461bcd60e51b815260040161067890613c11565b600f541561246d5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610678565b670de0b6b3a7640000600f55436010555f19601355600b805460ff19166001179055565b5f806124ab61249e6121c6565b6010546112299043613ff6565b90925090505f8260038111156124c3576124c3613bfd565b146125105760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b61251c81600f5461334f565b90925090505f82600381111561253457612534613bfd565b146125815760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b600f555043601055565b60048054604080516307dc0d1d60e41b815290515f9384936001600160a01b031692637dc0d1d092818301926020928290030181865afa1580156125d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125f59190613c39565b90505f80600c5411156127d457600d54156127ca575f826001600160a01b031663fc57d4df61262c6016546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561266e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126929190613be6565b905080670de0b6b3a764000011156127bf575f806126b8670de0b6b3a7640000846133c9565b90945091505f8460038111156126d0576126d0613bfd565b146126ed5760405162461bcd60e51b815260040161067890613f58565b6126f982600d546132f3565b90945091505f84600381111561271157612711613bfd565b1461272e5760405162461bcd60e51b815260040161067890613f58565b61274082670de0b6b3a7640000613330565b90945091505f84600381111561275857612758613bfd565b146127755760405162461bcd60e51b815260040161067890613f58565b61278182600c5461334f565b90945090505f84600381111561279957612799613bfd565b146127b65760405162461bcd60e51b815260040161067890613f58565b95945050505050565b600c54935050505090565b600c549250505090565b5f9250505090565b5f546001600160a01b031633146128055760405162461bcd60e51b815260040161067890613c11565b601554604080516001600160a01b03928316815291831660208301527ffb26401242c61b503dd09c29da64a5d4f451549f574b882a40bcdc64ee68b83c910160405180910390a1601580546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b031633148061289157506008546001600160a01b031633145b6128a8576128a160016017612ab0565b90506114d5565b670de0b6b3a764000082106128ff5760405162461bcd60e51b815260206004820152601d60248201527f74726561737572792070657263656e7420636170206f766572666c6f770000006044820152606401610678565b6008805460098054600a80546001600160a01b03198086166001600160a01b038c81169182179098559084168a8816179094559087905560408051948616808652602086019490945292949091169290917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e8910160405180910390a1604080516001600160a01b038085168252881660208201527f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac910160405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a1505f9695505050505050565b600480546040805163084bf5ab60e31b815290516001600160a01b039092169263425fad589282820192602092908290030181865afa158015612a48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a6c9190613c68565b15612aae5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610678565b565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836006811115612ae457612ae4613bfd565b836017811115612af657612af6613bfd565b6040805192835260208301919091525f9082015260600160405180910390a18260068111156114d5576114d5613bfd565b6004545f9081906001600160a01b03161561304757612b44612491565b60048054604051632fe3f38f60e11b815230928101929092526001600160a01b03858116602484015288811660448401528781166064840152608483018790525f92911690635fc7e71e9060a4016020604051808303815f875af1158015612bae573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd29190613be6565b90508015612bf257612be76002600a83613510565b5f9250925050613047565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c2f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c539190613be6565b14612c6457612be760026009612ab0565b866001600160a01b0316866001600160a01b031603612c8957612be76002600f612ab0565b845f03612c9c57612be76002600d612ab0565b5f198503612cb057612be76002600c612ab0565b5f80612cbd89898961358f565b90925090508115612cf157612ce4826006811115612cdd57612cdd613bfd565b6010612ab0565b5f94509450505050613047565b6004805460405163a78dc77560e01b81526001600160a01b0389811693820193909352602481018490525f928392169063a78dc775906044016040805180830381865afa158015612d44573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d689190614009565b90925090508115612de15760405162461bcd60e51b815260206004820152603760248201527f5641495f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c60448201527f4154455f414d4f554e545f5345495a455f4641494c45440000000000000000006064820152608401610678565b6040516370a0823160e01b81526001600160a01b038b811660048301528291908a16906370a0823190602401602060405180830381865afa158015612e28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e4c9190613be6565b1015612e9a5760405162461bcd60e51b815260206004820152601c60248201527f5641495f4c49515549444154455f5345495a455f544f4f5f4d554348000000006044820152606401610678565b60405163b2a02ff160e01b81526001600160a01b038c811660048301528b81166024830152604482018390525f91908a169063b2a02ff1906064016020604051808303815f875af1158015612ef1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f159190613be6565b90508015612f5c5760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610678565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f42d401f96718a0c42e5cea8108973f0022677b7e2e5f4ee19851b2de7a0394e79181900360a00190a1600480546040516347ef3b3b60e01b815230928101929092526001600160a01b038b811660248401528e811660448401528d811660648401526084830187905260a4830185905216906347ef3b3b9060c4015f604051808303815f87803b15801561301e575f80fd5b505af1158015613030573d5f803e3d5ffd5b505f925061303c915050565b975092955050505050505b94509492505050565b6001600160a01b0381166109ca5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610678565b6014546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906130d09033908590600401614059565b602060405180830381865afa1580156130eb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061310f9190613c68565b6109ca5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610678565b6004545f9081906001600160a01b031661316957505f905080613192565b613172836133e9565b61317a612a03565b613182612491565b61318d33858561358f565b915091505b9250929050565b5f6131af60405180602001604052805f81525090565b5f806131c1865f0151865f01516132f3565b90925090505f8260038111156131d9576131d9613bfd565b146131f7575060408051602081019091525f81529092509050613192565b5f8061321561320f6002670de0b6b3a764000061407c565b8461334f565b90925090505f82600381111561322d5761322d613bfd565b1461324f578160405180602001604052805f8152509550955050505050613192565b5f8061326383670de0b6b3a7640000613330565b90925090505f82600381111561327b5761327b613bfd565b146132885761328861409b565b60408051602081019091529081525f9a909950975050505050505050565b5f805f806132b486866138d5565b90925090505f8260038111156132cc576132cc613bfd565b146132dc575091505f9050613192565b5f6132e68261394a565b9350935050509250929050565b5f80835f0361330657505f905080613192565b83830283613314868361407c565b146133265760025f9250925050613192565b5f92509050613192565b5f80825f036133445750600190505f613192565b5f61318d848661407c565b5f80838301848110613365575f92509050613192565b60025f9250925050613192565b5f805f8061338087876138d5565b90925090505f82600381111561339857613398613bfd565b146133a8575091505f90506133c1565b6133ba6133b48261394a565b8661334f565b9350935050505b935093915050565b5f808383116133de57505f9050818303613192565b50600390505f613192565b5f81116109ca5760405162461bcd60e51b8152602060048201526014602482015273616d6f756e742063616e2774206265207a65726f60601b6044820152606401610678565b5f6114d58383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250613961565b5f6114d58383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061399a565b5f6114d583836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506139c8565b5f6114d583836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613a18565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084600681111561354457613544613bfd565b84601781111561355657613556613bfd565b604080519283526020830191909152810184905260600160405180910390a183600681111561358757613587613bfd565b949350505050565b5f805f805f61359e8787611c4b565b601654604051632770a7eb60e21b81526001600160a01b038d811660048301526024820186905294975092955090935091909116908190639dc29fac906044015f604051808303815f87803b1580156135f5575f80fd5b505af1158015613607573d5f803e3d5ffd5b5050600e546040516323b872dd60e01b81526001600160a01b038d811660048301529182166024820152604481018790525f935090841691506323b872dd906064016020604051808303815f875af1158015613665573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136899190613c68565b90506001811515146136dd5760405162461bcd60e51b815260206004820152601a60248201527f6661696c656420746f207472616e7366657220564149206665650000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa15801561372a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061374e9190613be6565b90505f61376461375e8389613464565b86613464565b6001600160a01b038c165f908152601260205260409020549091506137899086613464565b6001600160a01b03808d165f818152601260205260408082209490945560048054945163fd51a3ad60e01b81529081019290925260248201859052929091169063fd51a3ad906044016020604051808303815f875af11580156137ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138129190613be6565b9050801561385a5760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f613865898961342f565b90507f1db858e6f7e1a0d5e92c10c6507d42b3dabfe0a4867fe90c5a14d9963662ef7e8e8e836040516138b9939291906001600160a01b039384168152919092166020820152604081019190915260600190565b60405180910390a15f9e909d509b505050505050505050505050565b5f6138eb60405180602001604052805f81525090565b5f806138fa865f0151866132f3565b90925090505f82600381111561391257613912613bfd565b14613930575060408051602081019091525f81529092509050613192565b60408051602081019091529081525f969095509350505050565b80515f90610a5990670de0b6b3a76400009061407c565b5f8061396d84866140af565b905082858210156139915760405162461bcd60e51b815260040161067891906140c2565b50949350505050565b5f81848411156139bd5760405162461bcd60e51b815260040161067891906140c2565b506135878385613ff6565b5f8315806139d4575082155b156139e057505f6114d5565b5f6139eb84866140d4565b9050836139f8868361407c565b1483906139915760405162461bcd60e51b815260040161067891906140c2565b5f8183613a385760405162461bcd60e51b815260040161067891906140c2565b50613587838561407c565b6040805161018081019091525f808252602082019081526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001613a9c60405180602001604052805f81525090565b8152602001613ab660405180602001604052805f81525090565b8152602001613ad060405180602001604052805f81525090565b905290565b6001600160a01b03811681146109ca575f80fd5b5f805f60608486031215613afb575f80fd5b8335613b0681613ad5565b9250602084013591506040840135613b1d81613ad5565b809150509250925092565b5f60208284031215613b38575f80fd5b81356114d581613ad5565b5f60208284031215613b53575f80fd5b5035919050565b5f8060408385031215613b6b575f80fd5b8235613b7681613ad5565b946020939093013593505050565b5f805f60608486031215613b96575f80fd5b8335613ba181613ad5565b92506020840135613bb181613ad5565b929592945050506040919091013590565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b5f60208284031215613bf6575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b6020808252600e908201526d37b7363c9030b236b4b71031b0b760911b604082015260600190565b5f60208284031215613c49575f80fd5b81516114d581613ad5565b80518015158114613c63575f80fd5b919050565b5f60208284031215613c78575f80fd5b6114d582613c54565b634e487b7160e01b5f52604160045260245ffd5b8051613c6381613ad5565b5f6020808385031215613cb1575f80fd5b825167ffffffffffffffff80821115613cc8575f80fd5b818501915085601f830112613cdb575f80fd5b815181811115613ced57613ced613c81565b8060051b604051601f19603f83011681018181108582111715613d1257613d12613c81565b604052918252848201925083810185019188831115613d2f575f80fd5b938501935b82851015613d5457613d4585613c95565b84529385019392850192613d34565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215613d87575f80fd5b505082516020840151604085015160609095015191969095509092509050565b80516001600160601b0381168114613c63575f80fd5b5f805f805f805f60e0888a031215613dd3575f80fd5b613ddc88613c54565b965060208801519550613df160408901613c54565b94506060880151935060808801519250613e0d60a08901613da7565b9150613e1b60c08901613c54565b905092959891949750929550565b60208082526022908201527f5641495f4d494e545f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b5f60208284031215613e7b575f80fd5b6114d582613da7565b60208082526022908201527f5641495f4255524e5f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b6020808252602e908201527f5641495f43555252454e545f494e5445524553545f414d4f554e545f43414c4360408201526d155310551253d397d1905253115160921b606082015260800190565b60208082526024908201527f5641495f504153545f494e5445524553545f43414c43554c4154494f4e5f46416040820152631253115160e21b606082015260800190565b60208082526021908201527f5641495f52455041595f524154455f43414c43554c4154494f4e5f4641494c456040820152601160fa1b606082015260800190565b60208082526029908201527f5641495f544f54414c5f52455041595f414d4f554e545f43414c43554c41544960408201526813d397d1905253115160ba1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a5957610a59613fe2565b5f806040838503121561401a575f80fd5b505080516020909101519092909150565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f906135879083018461402b565b5f8261409657634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52600160045260245ffd5b80820180821115610a5957610a59613fe2565b602081525f6114d5602083018461402b565b8082028115828204841417610a5957610a59613fe256fea26469706673582212200ef15b6b7b15c1ccd6e2253973c2553bb634afc0c39fd76759cbd01b1c70c89264736f6c63430008190033", + "numDeployments": 4, + "solcInputHash": "cbc4287e135101fe4c78448d0f5f2ecc", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"LiquidateVAI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeAmount\",\"type\":\"uint256\"}],\"name\":\"MintFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"previousMintEnabledOnlyForPrimeHolder\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newMintEnabledOnlyForPrimeHolder\",\"type\":\"bool\"}],\"name\":\"MintOnlyForPrimeHolder\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mintVAIAmount\",\"type\":\"uint256\"}],\"name\":\"MintVAI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"NewAccessControl\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"oldComptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"newComptroller\",\"type\":\"address\"}],\"name\":\"NewComptroller\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPrime\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPrime\",\"type\":\"address\"}],\"name\":\"NewPrime\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"}],\"name\":\"NewTreasuryAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"}],\"name\":\"NewTreasuryGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldTreasuryPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"NewTreasuryPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBaseRateMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBaseRateMantissa\",\"type\":\"uint256\"}],\"name\":\"NewVAIBaseRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFloatRateMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFlatRateMantissa\",\"type\":\"uint256\"}],\"name\":\"NewVAIFloatRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMintCap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMintCap\",\"type\":\"uint256\"}],\"name\":\"NewVAIMintCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldReceiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newReceiver\",\"type\":\"address\"}],\"name\":\"NewVAIReceiver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldVaiToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newVaiToken\",\"type\":\"address\"}],\"name\":\"NewVaiToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayVAIAmount\",\"type\":\"uint256\"}],\"name\":\"RepayVAI\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_ID\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_VAI_MINT_INDEX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VAIUnitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"comptroller_\",\"type\":\"address\"}],\"name\":\"_setComptroller\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"_setTreasuryData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControl\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accrueVAIInterest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRateMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptroller\",\"outputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"floatRateMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"getMintableVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"getVAICalculateRepayAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"getVAIMinterInterestIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVAIRepayAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIRepayRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIRepayRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isVenusVAIInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"contract VTokenInterface\",\"name\":\"vTokenCollateral\",\"type\":\"address\"}],\"name\":\"liquidateVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintCap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintEnabledOnlyForPrimeHolder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"mintVAIAmount\",\"type\":\"uint256\"}],\"name\":\"mintVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"pastVAIInterest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingVAIControllerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"receiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repayVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repayVAIBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"setAccessControl\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBaseRateMantissa\",\"type\":\"uint256\"}],\"name\":\"setBaseRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFloatRateMantissa\",\"type\":\"uint256\"}],\"name\":\"setFloatRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_mintCap\",\"type\":\"uint256\"}],\"name\":\"setMintCap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"prime_\",\"type\":\"address\"}],\"name\":\"setPrimeToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newReceiver\",\"type\":\"address\"}],\"name\":\"setReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vai_\",\"type\":\"address\"}],\"name\":\"setVAIToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"toggleOnlyPrimeHolderMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiControllerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusVAIMinterIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setComptroller(address)\":{\"details\":\"Admin function to set a new comptroller\",\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setTreasuryData(address,address,uint256)\":{\"params\":{\"newTreasuryAddress\":\"New Treasury Address\",\"newTreasuryGuardian\":\"New Treasury Guardian address\",\"newTreasuryPercent\":\"New fee percentage for minting VAI that is sent to the treasury\"}},\"getMintableVAI(address)\":{\"params\":{\"minter\":\"The account to check mintable VAI\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\",\"_1\":\"Mintable amount (with 18 decimals)\"}},\"getVAIAddress()\":{\"returns\":{\"_0\":\"The address of VAI\"}},\"getVAICalculateRepayAmount(address,uint256)\":{\"params\":{\"borrower\":\"The address of the VAI borrower\",\"repayAmount\":\"The amount of VAI being returned\"},\"returns\":{\"_0\":\"Amount of VAI to be burned\",\"_1\":\"Amount of VAI the user needs to pay in current interest\",\"_2\":\"Amount of VAI the user needs to pay in past interest\"}},\"getVAIMinterInterestIndex(address)\":{\"params\":{\"minter\":\"Address of VAI minter\"},\"returns\":{\"_0\":\"uint256 Returns the interest rate index for a minter\"}},\"getVAIRepayAmount(address)\":{\"params\":{\"account\":\"The address of the VAI borrower\"},\"returns\":{\"_0\":\"(uint256) The total amount of VAI the user needs to repay\"}},\"getVAIRepayRate()\":{\"returns\":{\"_0\":\"uint256 Yearly VAI interest rate\"}},\"getVAIRepayRatePerBlock()\":{\"returns\":{\"_0\":\"uint256 Interest rate per bock\"}},\"liquidateVAI(address,uint256,address)\":{\"params\":{\"borrower\":\"The borrower of vai to be liquidated\",\"repayAmount\":\"The amount of the underlying borrowed asset to repay\",\"vTokenCollateral\":\"The market in which to seize collateral from the borrower\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"mintVAI(uint256)\":{\"details\":\"If the Comptroller address is not set, minting is a no-op and the function returns the success code.\",\"params\":{\"mintVAIAmount\":\"The amount of the VAI to be minted.\"},\"returns\":{\"_0\":\"0 on success, otherwise an error code\"}},\"repayVAI(uint256)\":{\"details\":\"If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\",\"params\":{\"amount\":\"The amount of VAI to be repaid.\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"repayVAIBehalf(address,uint256)\":{\"details\":\"If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\",\"params\":{\"amount\":\"The amount of VAI to be repaid.\",\"borrower\":\"The account to repay the debt for.\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"setAccessControl(address)\":{\"details\":\"Admin function to set the access control address\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"}},\"setBaseRate(uint256)\":{\"params\":{\"newBaseRateMantissa\":\"the base rate multiplied by 10**18\"}},\"setFloatRate(uint256)\":{\"params\":{\"newFloatRateMantissa\":\"the VAI float rate multiplied by 10**18\"}},\"setMintCap(uint256)\":{\"params\":{\"_mintCap\":\"the amount of VAI that can be minted\"}},\"setPrimeToken(address)\":{\"params\":{\"prime_\":\"The new address of the prime token contract\"}},\"setReceiver(address)\":{\"params\":{\"newReceiver\":\"the address of the VAI fee receiver\"}},\"setVAIToken(address)\":{\"params\":{\"vai_\":\"The new address of the VAI token contract\"}},\"toggleOnlyPrimeHolderMint()\":{\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}}},\"title\":\"VAI Comptroller\",\"version\":1},\"userdoc\":{\"events\":{\"LiquidateVAI(address,address,uint256,address,uint256)\":{\"notice\":\"Event emitted when a borrow is liquidated\"},\"MintFee(address,uint256)\":{\"notice\":\"Event emitted when VAIs are minted and fee are transferred\"},\"MintOnlyForPrimeHolder(bool,bool)\":{\"notice\":\"Emitted when mint for prime holder is changed\"},\"MintVAI(address,uint256)\":{\"notice\":\"Event emitted when VAI is minted\"},\"NewAccessControl(address,address)\":{\"notice\":\"Emitted when access control address is changed by admin\"},\"NewComptroller(address,address)\":{\"notice\":\"Emitted when Comptroller is changed\"},\"NewPrime(address,address)\":{\"notice\":\"Emitted when Prime is changed\"},\"NewTreasuryAddress(address,address)\":{\"notice\":\"Emitted when treasury address is changed\"},\"NewTreasuryGuardian(address,address)\":{\"notice\":\"Emitted when treasury guardian is changed\"},\"NewTreasuryPercent(uint256,uint256)\":{\"notice\":\"Emitted when treasury percent is changed\"},\"NewVAIBaseRate(uint256,uint256)\":{\"notice\":\"Emiitted when VAI base rate is changed\"},\"NewVAIFloatRate(uint256,uint256)\":{\"notice\":\"Emiitted when VAI float rate is changed\"},\"NewVAIMintCap(uint256,uint256)\":{\"notice\":\"Emiitted when VAI mint cap is changed\"},\"NewVAIReceiver(address,address)\":{\"notice\":\"Emiitted when VAI receiver address is changed\"},\"NewVaiToken(address,address)\":{\"notice\":\"Emitted when VAI token address is changed by admin\"},\"RepayVAI(address,address,uint256)\":{\"notice\":\"Event emitted when VAI is repaid\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_ID()\":{\"notice\":\"poolId for core Pool\"},\"INITIAL_VAI_MINT_INDEX()\":{\"notice\":\"Initial index used in interest computations\"},\"_setComptroller(address)\":{\"notice\":\"Sets a new comptroller\"},\"_setTreasuryData(address,address,uint256)\":{\"notice\":\"Update treasury data\"},\"accessControl()\":{\"notice\":\"Access control manager address\"},\"accrueVAIInterest()\":{\"notice\":\"Accrue interest on outstanding minted VAI\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"baseRateMantissa()\":{\"notice\":\"The base rate for stability fee\"},\"floatRateMantissa()\":{\"notice\":\"The float rate for stability fee\"},\"getMintableVAI(address)\":{\"notice\":\"Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\"},\"getVAIAddress()\":{\"notice\":\"Return the address of the VAI token\"},\"getVAICalculateRepayAmount(address,uint256)\":{\"notice\":\"Calculate how much VAI the user needs to repay\"},\"getVAIMinterInterestIndex(address)\":{\"notice\":\"Get the last updated interest index for a VAI Minter\"},\"getVAIRepayAmount(address)\":{\"notice\":\"Get the current total VAI a user needs to repay\"},\"getVAIRepayRate()\":{\"notice\":\"Gets yearly VAI interest rate based on the VAI price\"},\"getVAIRepayRatePerBlock()\":{\"notice\":\"Get interest rate per block\"},\"isVenusVAIInitialized()\":{\"notice\":\"The Venus VAI state initialized\"},\"liquidateVAI(address,uint256,address)\":{\"notice\":\"The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\"},\"mintCap()\":{\"notice\":\"VAI mint cap\"},\"mintEnabledOnlyForPrimeHolder()\":{\"notice\":\"Tracks if minting is enabled only for prime token holders. Only used if prime is set\"},\"mintVAI(uint256)\":{\"notice\":\"The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance. The amount minted must be less than the user's Account Liquidity and the mint vai limit.\"},\"pastVAIInterest(address)\":{\"notice\":\"Tracks the amount of mintedVAI of a user that represents the accrued interest\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingVAIControllerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"prime()\":{\"notice\":\"The address of the prime contract. It can be a ZERO address\"},\"receiver()\":{\"notice\":\"The address for VAI interest receiver\"},\"repayVAI(uint256)\":{\"notice\":\"The repay function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Before repaying VAI, users must first approve VAIController to access their VAI balance.\"},\"repayVAIBehalf(address,uint256)\":{\"notice\":\"The repay on behalf function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower). Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\"},\"setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"setBaseRate(uint256)\":{\"notice\":\"Set VAI borrow base rate\"},\"setFloatRate(uint256)\":{\"notice\":\"Set VAI borrow float rate\"},\"setMintCap(uint256)\":{\"notice\":\"Set VAI mint cap\"},\"setPrimeToken(address)\":{\"notice\":\"Set the prime token contract address\"},\"setReceiver(address)\":{\"notice\":\"Set VAI stability fee receiver address\"},\"setVAIToken(address)\":{\"notice\":\"Set the VAI token contract address\"},\"toggleOnlyPrimeHolderMint()\":{\"notice\":\"Toggle mint only for prime holder\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"vaiControllerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"vaiMintIndex()\":{\"notice\":\"Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\"},\"venusVAIMinterIndex(address)\":{\"notice\":\"The Venus VAI minter index as of the last time they accrued XVS\"},\"venusVAIState()\":{\"notice\":\"The Venus VAI state\"}},\"notice\":\"This is the implementation contract for the VAIUnitroller proxy\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Tokens/VAI/VAIController.sol\":\"VAIController\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\\n enum KeeperAction {\\n SetMinPrice,\\n SetMaxPrice,\\n ExitProtectionMode\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool cachingEnabled;\\n }\\n\\n /// @notice One item in an syncPriceBoundsAndProtections payload\\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\\n struct KeeperActionItem {\\n address asset;\\n KeeperAction action;\\n uint256 value;\\n }\\n\\n /// @notice One item in a setTokenConfigs payload\\n struct TokenConfigInput {\\n /// @notice The underlying asset address\\n address asset;\\n /// @notice Minimum time protection stays active after the last trigger (seconds)\\n uint64 cooldownPeriod;\\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\\n uint256 triggerThreshold;\\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\\n uint256 resetThreshold;\\n /// @notice Whether to enable bounded pricing immediately upon initialization\\n bool enableBoundedPricing;\\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\\n bool enableCaching;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n /// @notice Emitted when the per-asset transient caching flag is toggled\\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\\n error InvalidKeeperAction(uint8 action);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage. The transient\\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\\n * falls back to ResilientOracle on cache miss or when caching is disabled.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n /**\\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\\n * Empty `actions` is a no-op success.\\n * @param actions The list of keeper actions to apply\\n * @custom:access Only authorized keeper addresses\\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\\n */\\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param tokenConfig_ Token config input for the asset\\n * @custom:access Only Governance\\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param tokenConfigs_ Array of token config inputs, one per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if the input array is empty\\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\\n * @custom:error VAINotAllowed if any asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n /**\\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\\n * live spot instead of reading or writing the transient slots. The initial value is\\n * set via the `enableCaching` argument of `setTokenConfig`.\\n * @param asset The underlying asset address\\n * @param enabled Whether transient caching is enabled for this asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CachingEnabledUpdated\\n */\\n function setCachingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold,\\n bool cachingEnabled\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0xe223d88c17c0d752fdb33fa223b63ce124a798512f3d69f3800e9508e7dff931\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/IVAI.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-or-later\\n// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico\\n\\npragma solidity 0.8.25;\\n\\ninterface IVAI {\\n // --- Auth ---\\n function wards(address) external view returns (uint256);\\n function rely(address guy) external;\\n function deny(address guy) external;\\n\\n // --- BEP20 Data ---\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function version() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint256);\\n\\n function balanceOf(address) external view returns (uint256);\\n function allowance(address, address) external view returns (uint256);\\n function nonces(address) external view returns (uint256);\\n\\n event Approval(address indexed src, address indexed guy, uint256 wad);\\n event Transfer(address indexed src, address indexed dst, uint256 wad);\\n\\n // --- EIP712 niceties ---\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n // bytes32 public constant PERMIT_TYPEHASH = keccak256(\\\"Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)\\\");\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n // --- Token ---\\n function transfer(address dst, uint256 wad) external returns (bool);\\n function transferFrom(address src, address dst, uint256 wad) external returns (bool);\\n function mint(address usr, uint256 wad) external;\\n function burn(address usr, uint256 wad) external;\\n function approve(address usr, uint256 wad) external returns (bool);\\n\\n // --- Alias ---\\n function push(address usr, uint256 wad) external;\\n function pull(address usr, uint256 wad) external;\\n function move(address src, address dst, uint256 wad) external;\\n\\n // --- Approve by signature ---\\n function permit(\\n address holder,\\n address spender,\\n uint256 nonce,\\n uint256 expiry,\\n bool allowed,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0x9d7c391c50cdd8ddadd030694e1fd9ee3456861bc0cca2f2a28a714c6470d0b3\",\"license\":\"AGPL-3.0-or-later\"},\"contracts/Tokens/VAI/VAIController.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { VAIControllerErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { VToken } from \\\"../VTokens/VToken.sol\\\";\\nimport { VAIUnitroller } from \\\"./VAIUnitroller.sol\\\";\\nimport { VAIControllerInterface } from \\\"./VAIControllerInterface.sol\\\";\\nimport { IVAI } from \\\"./IVAI.sol\\\";\\nimport { IPrime } from \\\"../Prime/IPrime.sol\\\";\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\nimport { VAIControllerStorageG4 } from \\\"./VAIControllerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\n/**\\n * @title VAI Comptroller\\n * @author Venus\\n * @notice This is the implementation contract for the VAIUnitroller proxy\\n */\\ncontract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAIControllerErrorReporter, Exponential {\\n /// @notice Initial index used in interest computations\\n uint256 public constant INITIAL_VAI_MINT_INDEX = 1e18;\\n\\n /// poolId for core Pool\\n uint96 public constant CORE_POOL_ID = 0;\\n\\n /// @notice Emitted when Comptroller is changed\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /// @notice Emitted when mint for prime holder is changed\\n event MintOnlyForPrimeHolder(bool previousMintEnabledOnlyForPrimeHolder, bool newMintEnabledOnlyForPrimeHolder);\\n\\n /// @notice Emitted when Prime is changed\\n event NewPrime(address oldPrime, address newPrime);\\n\\n /// @notice Event emitted when VAI is minted\\n event MintVAI(address minter, uint256 mintVAIAmount);\\n\\n /// @notice Event emitted when VAI is repaid\\n event RepayVAI(address payer, address borrower, uint256 repayVAIAmount);\\n\\n /// @notice Event emitted when a borrow is liquidated\\n event LiquidateVAI(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n address vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /// @notice Emitted when treasury guardian is changed\\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\\n\\n /// @notice Emitted when treasury address is changed\\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\\n\\n /// @notice Emitted when treasury percent is changed\\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\\n\\n /// @notice Event emitted when VAIs are minted and fee are transferred\\n event MintFee(address minter, uint256 feeAmount);\\n\\n /// @notice Emiitted when VAI base rate is changed\\n event NewVAIBaseRate(uint256 oldBaseRateMantissa, uint256 newBaseRateMantissa);\\n\\n /// @notice Emiitted when VAI float rate is changed\\n event NewVAIFloatRate(uint256 oldFloatRateMantissa, uint256 newFlatRateMantissa);\\n\\n /// @notice Emiitted when VAI receiver address is changed\\n event NewVAIReceiver(address oldReceiver, address newReceiver);\\n\\n /// @notice Emiitted when VAI mint cap is changed\\n event NewVAIMintCap(uint256 oldMintCap, uint256 newMintCap);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /// @notice Emitted when VAI token address is changed by admin\\n event NewVaiToken(address oldVaiToken, address newVaiToken);\\n\\n function initialize() external onlyAdmin {\\n require(vaiMintIndex == 0, \\\"already initialized\\\");\\n\\n vaiMintIndex = INITIAL_VAI_MINT_INDEX;\\n accrualBlockNumber = getBlockNumber();\\n mintCap = type(uint256).max;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n function _become(VAIUnitroller unitroller) external {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance.\\n * The amount minted must be less than the user's Account Liquidity and the mint vai limit.\\n * @dev If the Comptroller address is not set, minting is a no-op and the function returns the success code.\\n * @param mintVAIAmount The amount of the VAI to be minted.\\n * @return 0 on success, otherwise an error code\\n */\\n // solhint-disable-next-line code-complexity\\n function mintVAI(uint256 mintVAIAmount) external nonReentrant returns (uint256) {\\n if (address(comptroller) == address(0)) {\\n return uint256(Error.NO_ERROR);\\n }\\n\\n require(comptroller.userPoolId(msg.sender) == CORE_POOL_ID, \\\"VAI mint only allowed in the core Pool\\\");\\n\\n _ensureNonzeroAmount(mintVAIAmount);\\n _ensureNotPaused();\\n accrueVAIInterest();\\n\\n uint256 err;\\n address minter = msg.sender;\\n address _vai = vai;\\n uint256 vaiTotalSupply = IVAI(_vai).totalSupply();\\n\\n uint256 vaiNewTotalSupply = add_(vaiTotalSupply, mintVAIAmount);\\n require(vaiNewTotalSupply <= mintCap, \\\"mint cap reached\\\");\\n\\n _updateProtectionStateForEnteredMarkets(minter);\\n\\n uint256 accountMintableVAI;\\n (err, accountMintableVAI) = getMintableVAI(minter);\\n require(err == uint256(Error.NO_ERROR), \\\"could not compute mintable amount\\\");\\n\\n // check that user have sufficient mintableVAI balance\\n require(mintVAIAmount <= accountMintableVAI, \\\"minting more than allowed\\\");\\n\\n // Calculate the minted balance based on interest index\\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\\n\\n if (totalMintedVAI > 0) {\\n uint256 repayAmount = getVAIRepayAmount(minter);\\n uint256 remainedAmount = sub_(repayAmount, totalMintedVAI);\\n pastVAIInterest[minter] = add_(pastVAIInterest[minter], remainedAmount);\\n totalMintedVAI = repayAmount;\\n }\\n\\n uint256 accountMintVAINew = add_(totalMintedVAI, mintVAIAmount);\\n err = comptroller.setMintedVAIOf(minter, accountMintVAINew);\\n require(err == uint256(Error.NO_ERROR), \\\"comptroller rejection\\\");\\n\\n uint256 remainedAmount;\\n if (treasuryPercent != 0) {\\n uint256 feeAmount = div_(mul_(mintVAIAmount, treasuryPercent), 1e18);\\n remainedAmount = sub_(mintVAIAmount, feeAmount);\\n IVAI(_vai).mint(treasuryAddress, feeAmount);\\n\\n emit MintFee(minter, feeAmount);\\n } else {\\n remainedAmount = mintVAIAmount;\\n }\\n\\n IVAI(_vai).mint(minter, remainedAmount);\\n vaiMinterInterestIndex[minter] = vaiMintIndex;\\n\\n emit MintVAI(minter, remainedAmount);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice The repay function transfers VAI interest into the protocol and burns the rest,\\n * reducing the borrower's borrow balance. Before repaying VAI, users must first approve\\n * VAIController to access their VAI balance.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAI(uint256 amount) external nonReentrant returns (uint256, uint256) {\\n return _repayVAI(msg.sender, amount);\\n }\\n\\n /**\\n * @notice The repay on behalf function transfers VAI interest into the protocol and burns the rest,\\n * reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower).\\n * Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param borrower The account to repay the debt for.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAIBehalf(address borrower, uint256 amount) external nonReentrant returns (uint256, uint256) {\\n _ensureNonzeroAddress(borrower);\\n return _repayVAI(borrower, amount);\\n }\\n\\n /**\\n * @dev Checks the parameters and the protocol state, accrues interest, and invokes repayVAIFresh.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param borrower The account to repay the debt for.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function _repayVAI(address borrower, uint256 amount) internal returns (uint256, uint256) {\\n if (address(comptroller) == address(0)) {\\n return (0, 0);\\n }\\n _ensureNonzeroAmount(amount);\\n _ensureNotPaused();\\n\\n accrueVAIInterest();\\n return repayVAIFresh(msg.sender, borrower, amount);\\n }\\n\\n /**\\n * @dev Repay VAI, expecting interest to be accrued\\n * @dev Borrowed VAIs are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the VAI\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of VAI being repaid\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAIFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256, uint256) {\\n (uint256 burn, uint256 partOfCurrentInterest, uint256 partOfPastInterest) = getVAICalculateRepayAmount(\\n borrower,\\n repayAmount\\n );\\n\\n IVAI _vai = IVAI(vai);\\n _vai.burn(payer, burn);\\n bool success = _vai.transferFrom(payer, receiver, partOfCurrentInterest);\\n require(success == true, \\\"failed to transfer VAI fee\\\");\\n\\n uint256 vaiBalanceBorrower = comptroller.mintedVAIs(borrower);\\n\\n uint256 accountVAINew = sub_(sub_(vaiBalanceBorrower, burn), partOfPastInterest);\\n pastVAIInterest[borrower] = sub_(pastVAIInterest[borrower], partOfPastInterest);\\n\\n uint256 error = comptroller.setMintedVAIOf(borrower, accountVAINew);\\n // We have to revert upon error since side-effects already happened at this point\\n require(error == uint256(Error.NO_ERROR), \\\"comptroller rejection\\\");\\n\\n uint256 repaidAmount = add_(burn, partOfCurrentInterest);\\n emit RepayVAI(payer, borrower, repaidAmount);\\n\\n return (uint256(Error.NO_ERROR), repaidAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of vai to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external nonReentrant returns (uint256, uint256) {\\n _ensureNotPaused();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != uint256(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateVAIFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateVAIFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral by repay borrowers VAI.\\n * The collateral seized is transferred to the liquidator.\\n * @dev If the Comptroller address is not set, liquidation is a no-op and the function returns the success code.\\n * @param liquidator The address repaying the VAI and seizing collateral\\n * @param borrower The borrower of this VAI to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the VAI to repay\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function liquidateVAIFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint256, uint256) {\\n if (address(comptroller) != address(0)) {\\n accrueVAIInterest();\\n\\n /* Fail if liquidate not allowed */\\n uint256 allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n //if (vTokenCollateral.accrualBlockNumber() != accrualBlockNumber) {\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayVAI fails */\\n (uint256 repayBorrowError, uint256 actualRepayAmount) = repayVAIFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint256(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateVAICalculateSeizeTokens(\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(\\n amountSeizeError == uint256(Error.NO_ERROR),\\n \\\"VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\"\\n );\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"VAI_LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n uint256 seizeError;\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint256(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateVAI(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint256(Error.NO_ERROR), actualRepayAmount);\\n }\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new comptroller\\n * @dev Admin function to set a new comptroller\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface comptroller_) external returns (uint256) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n comptroller = comptroller_;\\n emit NewComptroller(oldComptroller, comptroller_);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the prime token contract address\\n * @param prime_ The new address of the prime token contract\\n */\\n function setPrimeToken(address prime_) external onlyAdmin {\\n emit NewPrime(prime, prime_);\\n prime = prime_;\\n }\\n\\n /**\\n * @notice Set the VAI token contract address\\n * @param vai_ The new address of the VAI token contract\\n */\\n function setVAIToken(address vai_) external onlyAdmin {\\n emit NewVaiToken(vai, vai_);\\n vai = vai_;\\n }\\n\\n /**\\n * @notice Toggle mint only for prime holder\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function toggleOnlyPrimeHolderMint() external returns (uint256) {\\n _ensureAllowed(\\\"toggleOnlyPrimeHolderMint()\\\");\\n\\n if (!mintEnabledOnlyForPrimeHolder && prime == address(0)) {\\n return uint256(Error.REJECTION);\\n }\\n\\n emit MintOnlyForPrimeHolder(mintEnabledOnlyForPrimeHolder, !mintEnabledOnlyForPrimeHolder);\\n mintEnabledOnlyForPrimeHolder = !mintEnabledOnlyForPrimeHolder;\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account total supply balance.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountAmountLocalVars {\\n uint256 oErr;\\n MathError mErr;\\n uint256 sumSupply;\\n uint256 marketSupply;\\n uint256 sumBorrowPlusEffects;\\n uint256 vTokenBalance;\\n uint256 borrowBalance;\\n uint256 exchangeRateMantissa;\\n uint256 collateralPriceMantissa;\\n uint256 debtPriceMantissa;\\n Exp exchangeRate;\\n Exp collateralPrice;\\n Exp debtPrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate\\n * If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\\n * @param minter The account to check mintable VAI\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\\n * @return Mintable amount (with 18 decimals)\\n */\\n // solhint-disable-next-line code-complexity\\n function getMintableVAI(address minter) public view returns (uint256, uint256) {\\n if (mintEnabledOnlyForPrimeHolder && !IPrime(prime).isUserPrimeHolder(minter)) {\\n return (uint256(Error.REJECTION), 0);\\n }\\n\\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\\n IDeviationBoundedOracle boundedOracle = comptroller.deviationBoundedOracle();\\n\\n AccountAmountLocalVars memory vars; // Holds all our calculation results\\n\\n uint256 accountMintableVAI;\\n uint256 i;\\n\\n /**\\n * We use this formula to calculate mintable VAI amount.\\n * totalSupplyAmount * VAIMintRate - (totalBorrowAmount + mintedVAIOf)\\n */\\n uint256 marketsCount = enteredMarkets.length;\\n for (i = 0; i < marketsCount; i++) {\\n (vars.oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = enteredMarkets[i]\\n .getAccountSnapshot(minter);\\n if (vars.oErr != 0) {\\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (uint256(Error.SNAPSHOT_ERROR), 0);\\n }\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n // Get bounded prices: collateral price for supply valuation, debt price for borrow valuation\\n (vars.collateralPriceMantissa, vars.debtPriceMantissa) = boundedOracle.getBoundedPricesView(\\n address(enteredMarkets[i])\\n );\\n if (vars.collateralPriceMantissa == 0 || vars.debtPriceMantissa == 0) {\\n return (uint256(Error.PRICE_ERROR), 0);\\n }\\n vars.collateralPrice = Exp({ mantissa: vars.collateralPriceMantissa });\\n vars.debtPrice = Exp({ mantissa: vars.debtPriceMantissa });\\n\\n (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.collateralPrice);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n // marketSupply = tokensToDenom * vTokenBalance\\n (vars.mErr, vars.marketSupply) = mulScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (, uint256 collateralFactorMantissa, , , , , ) = comptroller.markets(address(enteredMarkets[i]));\\n (vars.mErr, vars.marketSupply) = mulUInt(vars.marketSupply, collateralFactorMantissa);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, vars.marketSupply) = divUInt(vars.marketSupply, 1e18);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, vars.sumSupply) = addUInt(vars.sumSupply, vars.marketSupply);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n // sumBorrowPlusEffects += debtPrice * borrowBalance\\n (vars.mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(\\n vars.debtPrice,\\n vars.borrowBalance,\\n vars.sumBorrowPlusEffects\\n );\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n }\\n\\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\\n uint256 repayAmount = 0;\\n\\n if (totalMintedVAI > 0) {\\n repayAmount = getVAIRepayAmount(minter);\\n }\\n\\n (vars.mErr, vars.sumBorrowPlusEffects) = addUInt(vars.sumBorrowPlusEffects, repayAmount);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, accountMintableVAI) = mulUInt(vars.sumSupply, comptroller.vaiMintRate());\\n require(vars.mErr == MathError.NO_ERROR, \\\"VAI_MINT_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (vars.mErr, accountMintableVAI) = divUInt(accountMintableVAI, 10000);\\n require(vars.mErr == MathError.NO_ERROR, \\\"VAI_MINT_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (vars.mErr, accountMintableVAI) = subUInt(accountMintableVAI, vars.sumBorrowPlusEffects);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.REJECTION), 0);\\n }\\n\\n return (uint256(Error.NO_ERROR), accountMintableVAI);\\n }\\n\\n /**\\n * @notice Update treasury data\\n * @param newTreasuryGuardian New Treasury Guardian address\\n * @param newTreasuryAddress New Treasury Address\\n * @param newTreasuryPercent New fee percentage for minting VAI that is sent to the treasury\\n */\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256) {\\n // Check caller is admin\\n if (!(msg.sender == admin || msg.sender == treasuryGuardian)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_TREASURY_OWNER_CHECK);\\n }\\n\\n require(newTreasuryPercent < 1e18, \\\"treasury percent cap overflow\\\");\\n\\n address oldTreasuryGuardian = treasuryGuardian;\\n address oldTreasuryAddress = treasuryAddress;\\n uint256 oldTreasuryPercent = treasuryPercent;\\n\\n treasuryGuardian = newTreasuryGuardian;\\n treasuryAddress = newTreasuryAddress;\\n treasuryPercent = newTreasuryPercent;\\n\\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Gets yearly VAI interest rate based on the VAI price\\n * @return uint256 Yearly VAI interest rate\\n */\\n function getVAIRepayRate() public view returns (uint256) {\\n ResilientOracleInterface oracle = comptroller.oracle();\\n MathError mErr;\\n\\n if (baseRateMantissa > 0) {\\n if (floatRateMantissa > 0) {\\n uint256 oraclePrice = oracle.getUnderlyingPrice(getVAIAddress());\\n if (1e18 > oraclePrice) {\\n uint256 delta;\\n uint256 rate;\\n\\n (mErr, delta) = subUInt(1e18, oraclePrice);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = mulUInt(delta, floatRateMantissa);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = divUInt(delta, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, rate) = addUInt(delta, baseRateMantissa);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n return rate;\\n } else {\\n return baseRateMantissa;\\n }\\n } else {\\n return baseRateMantissa;\\n }\\n } else {\\n return 0;\\n }\\n }\\n\\n /**\\n * @notice Get interest rate per block\\n * @return uint256 Interest rate per bock\\n */\\n function getVAIRepayRatePerBlock() public view returns (uint256) {\\n uint256 yearlyRate = getVAIRepayRate();\\n\\n MathError mErr;\\n uint256 rate;\\n\\n (mErr, rate) = divUInt(yearlyRate, getBlocksPerYear());\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Get the last updated interest index for a VAI Minter\\n * @param minter Address of VAI minter\\n * @return uint256 Returns the interest rate index for a minter\\n */\\n function getVAIMinterInterestIndex(address minter) public view returns (uint256) {\\n uint256 storedIndex = vaiMinterInterestIndex[minter];\\n // If the user minted VAI before the stability fee was introduced, accrue\\n // starting from stability fee launch\\n if (storedIndex == 0) {\\n return INITIAL_VAI_MINT_INDEX;\\n }\\n return storedIndex;\\n }\\n\\n /**\\n * @notice Get the current total VAI a user needs to repay\\n * @param account The address of the VAI borrower\\n * @return (uint256) The total amount of VAI the user needs to repay\\n */\\n function getVAIRepayAmount(address account) public view returns (uint256) {\\n MathError mErr;\\n uint256 delta;\\n\\n uint256 amount = comptroller.mintedVAIs(account);\\n uint256 interest = pastVAIInterest[account];\\n uint256 totalMintedVAI;\\n uint256 newInterest;\\n\\n (mErr, totalMintedVAI) = subUInt(amount, interest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = subUInt(vaiMintIndex, getVAIMinterInterestIndex(account));\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, newInterest) = mulUInt(delta, totalMintedVAI);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, newInterest) = divUInt(newInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, amount) = addUInt(amount, newInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n return amount;\\n }\\n\\n /**\\n * @notice Calculate how much VAI the user needs to repay\\n * @param borrower The address of the VAI borrower\\n * @param repayAmount The amount of VAI being returned\\n * @return Amount of VAI to be burned\\n * @return Amount of VAI the user needs to pay in current interest\\n * @return Amount of VAI the user needs to pay in past interest\\n */\\n function getVAICalculateRepayAmount(\\n address borrower,\\n uint256 repayAmount\\n ) public view returns (uint256, uint256, uint256) {\\n MathError mErr;\\n uint256 totalRepayAmount = getVAIRepayAmount(borrower);\\n uint256 currentInterest;\\n\\n (mErr, currentInterest) = subUInt(totalRepayAmount, comptroller.mintedVAIs(borrower));\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, currentInterest) = addUInt(pastVAIInterest[borrower], currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n uint256 burn;\\n uint256 partOfCurrentInterest = currentInterest;\\n uint256 partOfPastInterest = pastVAIInterest[borrower];\\n\\n if (repayAmount >= totalRepayAmount) {\\n (mErr, burn) = subUInt(totalRepayAmount, currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n } else {\\n uint256 delta;\\n\\n (mErr, delta) = mulUInt(repayAmount, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PART_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = divUInt(delta, totalRepayAmount);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PART_CALCULATION_FAILED\\\");\\n\\n uint256 totalMintedAmount;\\n (mErr, totalMintedAmount) = subUInt(totalRepayAmount, currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_MINTED_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, burn) = mulUInt(totalMintedAmount, delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, burn) = divUInt(burn, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfCurrentInterest) = mulUInt(currentInterest, delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfCurrentInterest) = divUInt(partOfCurrentInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfPastInterest) = mulUInt(pastVAIInterest[borrower], delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PAST_INTEREST_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfPastInterest) = divUInt(partOfPastInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PAST_INTEREST_CALCULATION_FAILED\\\");\\n }\\n\\n return (burn, partOfCurrentInterest, partOfPastInterest);\\n }\\n\\n /**\\n * @notice Accrue interest on outstanding minted VAI\\n */\\n function accrueVAIInterest() public {\\n MathError mErr;\\n uint256 delta;\\n\\n (mErr, delta) = mulUInt(getVAIRepayRatePerBlock(), getBlockNumber() - accrualBlockNumber);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_INTEREST_ACCRUE_FAILED\\\");\\n\\n (mErr, delta) = addUInt(delta, vaiMintIndex);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_INTEREST_ACCRUE_FAILED\\\");\\n\\n vaiMintIndex = delta;\\n accrualBlockNumber = getBlockNumber();\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlAddress New address for the access control\\n */\\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\\n _ensureNonzeroAddress(newAccessControlAddress);\\n\\n address oldAccessControlAddress = accessControl;\\n accessControl = newAccessControlAddress;\\n emit NewAccessControl(oldAccessControlAddress, accessControl);\\n }\\n\\n /**\\n * @notice Set VAI borrow base rate\\n * @param newBaseRateMantissa the base rate multiplied by 10**18\\n */\\n function setBaseRate(uint256 newBaseRateMantissa) external {\\n _ensureAllowed(\\\"setBaseRate(uint256)\\\");\\n\\n uint256 old = baseRateMantissa;\\n baseRateMantissa = newBaseRateMantissa;\\n emit NewVAIBaseRate(old, baseRateMantissa);\\n }\\n\\n /**\\n * @notice Set VAI borrow float rate\\n * @param newFloatRateMantissa the VAI float rate multiplied by 10**18\\n */\\n function setFloatRate(uint256 newFloatRateMantissa) external {\\n _ensureAllowed(\\\"setFloatRate(uint256)\\\");\\n\\n uint256 old = floatRateMantissa;\\n floatRateMantissa = newFloatRateMantissa;\\n emit NewVAIFloatRate(old, floatRateMantissa);\\n }\\n\\n /**\\n * @notice Set VAI stability fee receiver address\\n * @param newReceiver the address of the VAI fee receiver\\n */\\n function setReceiver(address newReceiver) external onlyAdmin {\\n _ensureNonzeroAddress(newReceiver);\\n\\n address old = receiver;\\n receiver = newReceiver;\\n emit NewVAIReceiver(old, newReceiver);\\n }\\n\\n /**\\n * @notice Set VAI mint cap\\n * @param _mintCap the amount of VAI that can be minted\\n */\\n function setMintCap(uint256 _mintCap) external {\\n _ensureAllowed(\\\"setMintCap(uint256)\\\");\\n\\n uint256 old = mintCap;\\n mintCap = _mintCap;\\n emit NewVAIMintCap(old, _mintCap);\\n }\\n\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n function getBlocksPerYear() public view virtual returns (uint256) {\\n return 70080000; //(24 * 60 * 60 * 365) / 0.45;\\n }\\n\\n /**\\n * @notice Return the address of the VAI token\\n * @return The address of VAI\\n */\\n function getVAIAddress() public view virtual returns (address) {\\n return vai;\\n }\\n\\n modifier onlyAdmin() {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n _;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n function _ensureAllowed(string memory functionSig) private view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /// @dev Reverts if the protocol is paused\\n function _ensureNotPaused() private view {\\n require(!comptroller.protocolPaused(), \\\"protocol is paused\\\");\\n }\\n\\n /// @dev Reverts if the passed address is zero\\n function _ensureNonzeroAddress(address someone) private pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @dev Reverts if the passed amount is zero\\n function _ensureNonzeroAmount(uint256 amount) private pure {\\n require(amount > 0, \\\"amount can't be zero\\\");\\n }\\n\\n /// @dev Persists the DBO protection window for every market the minter has entered, so VAI minting\\n /// records the same on-chain price history as the borrow path. Extracted from `mintVAI` to avoid\\n /// stack-too-deep in that function.\\n function _updateProtectionStateForEnteredMarkets(address minter) private {\\n IDeviationBoundedOracle dbo = comptroller.deviationBoundedOracle();\\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\\n uint256 enteredLength = enteredMarkets.length;\\n for (uint256 i; i < enteredLength; ++i) {\\n dbo.updateProtectionState(address(enteredMarkets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x830579a0fc7a1b46296f1b647cfa70b63dba40018429731b1bab6812f32fb745\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\n\\ncontract VAIUnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public vaiControllerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingVAIControllerImplementation;\\n}\\n\\ncontract VAIControllerStorageG1 is VAIUnitrollerAdminStorage {\\n ComptrollerInterface public comptroller;\\n\\n struct VenusVAIState {\\n /// @notice The last updated venusVAIMintIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice The Venus VAI state\\n VenusVAIState public venusVAIState;\\n\\n /// @notice The Venus VAI state initialized\\n bool public isVenusVAIInitialized;\\n\\n /// @notice The Venus VAI minter index as of the last time they accrued XVS\\n mapping(address => uint256) public venusVAIMinterIndex;\\n}\\n\\ncontract VAIControllerStorageG2 is VAIControllerStorageG1 {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n\\n /// @notice Guard variable for re-entrancy checks\\n bool internal _notEntered;\\n\\n /// @notice The base rate for stability fee\\n uint256 public baseRateMantissa;\\n\\n /// @notice The float rate for stability fee\\n uint256 public floatRateMantissa;\\n\\n /// @notice The address for VAI interest receiver\\n address public receiver;\\n\\n /// @notice Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\\n uint256 public vaiMintIndex;\\n\\n /// @notice Block number that interest was last accrued at\\n uint256 internal accrualBlockNumber;\\n\\n /// @notice Global vaiMintIndex as of the most recent balance-changing action for user\\n mapping(address => uint256) internal vaiMinterInterestIndex;\\n\\n /// @notice Tracks the amount of mintedVAI of a user that represents the accrued interest\\n mapping(address => uint256) public pastVAIInterest;\\n\\n /// @notice VAI mint cap\\n uint256 public mintCap;\\n\\n /// @notice Access control manager address\\n address public accessControl;\\n}\\n\\ncontract VAIControllerStorageG3 is VAIControllerStorageG2 {\\n /// @notice The address of the prime contract. It can be a ZERO address\\n address public prime;\\n\\n /// @notice Tracks if minting is enabled only for prime token holders. Only used if prime is set\\n bool public mintEnabledOnlyForPrimeHolder;\\n}\\n\\ncontract VAIControllerStorageG4 is VAIControllerStorageG3 {\\n /// @notice The address of the VAI token\\n address internal vai;\\n}\\n\",\"keccak256\":\"0x75295c0c9d1e5e7b8726b0d43c260975eb4d8d0b76325360c39723b996b95603\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIUnitroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { VAIControllerErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { VAIUnitrollerAdminStorage } from \\\"./VAIControllerStorage.sol\\\";\\n\\n/**\\n * @title VAI Unitroller\\n * @author Venus\\n * @notice This is the proxy contract for the VAIComptroller\\n */\\ncontract VAIUnitroller is VAIUnitrollerAdminStorage, VAIControllerErrorReporter {\\n /**\\n * @notice Emitted when pendingVAIControllerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingVAIControllerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint256) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingVAIControllerImplementation;\\n\\n pendingVAIControllerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint256) {\\n // Check caller is pendingImplementation\\n if (msg.sender != pendingVAIControllerImplementation) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = vaiControllerImplementation;\\n address oldPendingImplementation = pendingVAIControllerImplementation;\\n\\n vaiControllerImplementation = pendingVAIControllerImplementation;\\n\\n pendingVAIControllerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, vaiControllerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint256) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint256) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n fallback() external {\\n // delegate all other functions to current implementation\\n (bool success, ) = vaiControllerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize())\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize())\\n }\\n default {\\n return(free_mem_ptr, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe33306ad442bbfe51c50572f91005d98cb657649316ca29aa650fa679dbca86\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b506143058061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061028b575f3560e01c8063691e45ac11610161578063b49b1005116100ca578063d24febad11610084578063d24febad146105a1578063e44e6168146105b4578063ee1fa41e146105fa578063f20fd8f41461060e578063f7260d3e1461062d578063f851a44014610640575f80fd5b8063b49b100514610547578063b9ee87261461054f578063c32094c714610557578063c5f956af1461056a578063c7ee005e1461057d578063cbeb2b2814610590575f80fd5b806378c2f9221161011b57806378c2f922146104de5780637a37c5d0146104f15780638129fc1c14610510578063b06bb42614610518578063b2b481bc1461052b578063b2eafc3914610534575f80fd5b8063691e45ac1461046f5780636fe74a211461049d578063718da7ee146104b0578063741de148146104c357806375c3de43146104cd57806376c71ca1146104d5575f80fd5b80633785d1d6116102035780635ce73240116101bd5780635ce732401461040c5780635fe3b5671461041557806360c954ef1461042857806361b3311c146104455780636509795414610458578063657bdf9414610467575f80fd5b80633785d1d6146103a45780633b5a0a64146103b75780633b72fbef146103ca5780634070a0c9146103d35780634576b5db146103e65780634712ee7d146103f9575f80fd5b80631d08837b116102545780631d08837b146103265780631d504dc6146103395780631f040ff51461034c578063234f89771461035f57806324650602146103725780632678224714610391575f80fd5b80623b58841461028f57806304ef9d58146102bf57806311b3d5e7146102d657806313007d55146102fe57806319129e5a14610311575b5f80fd5b6002546102a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102c8600a5481565b6040519081526020016102b6565b6102e96102e4366004613ccd565b610652565b604080519283526020830191909152016102b6565b6014546102a2906001600160a01b031681565b61032461031f366004613d0c565b61074d565b005b610324610334366004613d27565b6107e1565b610324610347366004613d0c565b610854565b6102e961035a366004613d3e565b6109cd565b6102c861036d366004613d0c565b610a2a565b6102c8610380366004613d0c565b60076020525f908152604090205481565b6001546102a2906001600160a01b031681565b6102e96103b2366004613d0c565b610a5f565b6103246103c5366004613d27565b6113a1565b6102c8600c5481565b6103246103e1366004613d27565b611415565b6102c86103f4366004613d0c565b611487565b6102c8610407366004613d27565b61150b565b6102c8600d5481565b6004546102a2906001600160a01b031681565b6006546104359060ff1681565b60405190151581526020016102b6565b610324610453366004613d0c565b611b18565b6102c8670de0b6b3a764000081565b6102c8611baa565b61048261047d366004613d3e565b611c83565b604080519384526020840192909252908201526060016102b6565b6102e96104ab366004613d27565b612120565b6103246104be366004613d0c565b612172565b63042d56006102c8565b6102c86121fe565b6102c860135481565b6102c86104ec366004613d0c565b61224f565b6104f85f81565b6040516001600160601b0390911681526020016102b6565b610324612436565b6003546102a2906001600160a01b031681565b6102c8600f5481565b6008546102a2906001600160a01b031681565b6103246124c9565b6102c86125c3565b610324610565366004613d0c565b612814565b6009546102a2906001600160a01b031681565b6015546102a2906001600160a01b031681565b6016546001600160a01b03166102a2565b6102c86105af366004613d68565b6128a6565b6005546105d6906001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016102b6565b60155461043590600160a01b900460ff1681565b6102c861061c366004613d0c565b60126020525f908152604090205481565b600e546102a2906001600160a01b031681565b5f546102a2906001600160a01b031681565b600b545f90819060ff166106815760405162461bcd60e51b815260040161067890613da6565b60405180910390fd5b600b805460ff19169055610693612a3b565b5f836001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303815f875af11580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190613dca565b905080156107245761071981600681111561071257610712613de1565b6008612ae8565b5f9250925050610736565b61073033878787612b5f565b92509250505b600b805460ff191660011790559094909350915050565b5f546001600160a01b031633146107765760405162461bcd60e51b815260040161067890613df5565b61077f81613088565b601480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd491015b60405180910390a15050565b6108166040518060400160405280601481526020017373657442617365526174652875696e743235362960601b8152506130d6565b600c80549082905560408051828152602081018490527fc84c32795e68685ec107b0e94ae126ef464095f342c7e2e0fec06a23d2e8677e91016107d5565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b49190613e1d565b6001600160a01b0316336001600160a01b0316146109245760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610678565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610961573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109859190613dca565b156109ca5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610678565b50565b600b545f90819060ff166109f35760405162461bcd60e51b815260040161067890613da6565b600b805460ff19169055610a0684613088565b610a108484613183565b91509150600b805460ff1916600117905590939092509050565b6001600160a01b0381165f90815260116020526040812054808203610a595750670de0b6b3a764000092915050565b92915050565b6015545f908190600160a01b900460ff168015610ae55750601554604051630e3da90d60e21b81526001600160a01b038581166004830152909116906338f6a43490602401602060405180830381865afa158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae39190613e4c565b155b15610af5576002935f9350915050565b60048054604051632aff3bff60e21b81526001600160a01b03868116938201939093525f929091169063abfceffc906024015f60405180830381865afa158015610b41573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b689190810190613e84565b90505f60045f9054906101000a90046001600160a01b03166001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bdf9190613e1d565b9050610be9613c07565b82515f9081905b808210156110e557858281518110610c0a57610c0a613f44565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038b811660048301529091169063c37f68e290602401608060405180830381865afa158015610c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613f58565b60e088015260c087015260a086015280855215610ca75760035b995f9950975050505050505050565b60405180602001604052808560e00151815250846101400181905250846001600160a01b03166388142b6b878481518110610ce457610ce4613f44565b60200260200101516040518263ffffffff1660e01b8152600401610d1791906001600160a01b0391909116815260200190565b6040805180830381865afa158015610d31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d559190613f8b565b61012086015261010085018190521580610d725750610120840151155b15610d7e576004610c98565b604080516020808201835261010087015182526101608701918252825190810190925261012086015182526101808601919091526101408501519051610dc491906131d1565b85602001866101a001829052826003811115610de257610de2613de1565b6003811115610df357610df3613de1565b9052505f905084602001516003811115610e0f57610e0f613de1565b14610e1b576005610c98565b610e2e846101a001518560a001516132de565b6060860181905260208601826003811115610e4b57610e4b613de1565b6003811115610e5c57610e5c613de1565b9052505f905084602001516003811115610e7857610e78613de1565b14610e84576005610c98565b60045486515f916001600160a01b031690638e8f294b90899086908110610ead57610ead613f44565b60200260200101516040518263ffffffff1660e01b8152600401610ee091906001600160a01b0391909116815260200190565b60e060405180830381865afa158015610efb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f1f9190613fc3565b5050505050915050610f3585606001518261332b565b6060870181905260208701826003811115610f5257610f52613de1565b6003811115610f6357610f63613de1565b9052505f905085602001516003811115610f7f57610f7f613de1565b14610f975760055b9a5f9a5098505050505050505050565b610fad8560600151670de0b6b3a7640000613368565b6060870181905260208701826003811115610fca57610fca613de1565b6003811115610fdb57610fdb613de1565b9052505f905085602001516003811115610ff757610ff7613de1565b14611003576005610f87565b61101585604001518660600151613387565b604087018190526020870182600381111561103257611032613de1565b600381111561104357611043613de1565b9052505f90508560200151600381111561105f5761105f613de1565b1461106b576005610f87565b6110838561018001518660c0015187608001516133aa565b60808701819052602087018260038111156110a0576110a0613de1565b60038111156110b1576110b1613de1565b9052505f9050856020015160038111156110cd576110cd613de1565b146110d9576005610f87565b50600190910190610bf0565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611132573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111569190613dca565b90505f811561116b576111688b61224f565b90505b611179866080015182613387565b608088018190526020880182600381111561119657611196613de1565b60038111156111a7576111a7613de1565b9052505f9050866020015160038111156111c3576111c3613de1565b146111dc5760055b9b5f9b509950505050505050505050565b61125d866040015160045f9054906101000a90046001600160a01b03166001600160a01b031663bec04f726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611234573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112589190613dca565b61332b565b8760200181975082600381111561127657611276613de1565b600381111561128757611287613de1565b9052505f9050866020015160038111156112a3576112a3613de1565b146112c05760405162461bcd60e51b81526004016106789061402f565b6112cc85612710613368565b876020018197508260038111156112e5576112e5613de1565b60038111156112f6576112f6613de1565b9052505f90508660200151600381111561131257611312613de1565b1461132f5760405162461bcd60e51b81526004016106789061402f565b61133d858760800151613401565b8760200181975082600381111561135657611356613de1565b600381111561136757611367613de1565b9052505f90508660200151600381111561138357611383613de1565b1461138f5760026111cb565b5f9b949a509398505050505050505050565b6113d760405180604001604052806015815260200174736574466c6f6174526174652875696e743235362960581b8152506130d6565b600d80549082905560408051828152602081018490527f546fb35dbbd92233aecc22b5a11a6791e5db7ec14f62e49cbac2a10c0437f56191016107d5565b611449604051806040016040528060138152602001727365744d696e744361702875696e743235362960681b8152506130d6565b601380549082905560408051828152602081018490527f43862b3eea2df8fce70329f3f84cbcad220f47a73be46c5e00df25165a6e169591016107d5565b5f80546001600160a01b031633146114a557610a5960016002612ae8565b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d910160405180910390a15f5b9392505050565b600b545f9060ff1661152f5760405162461bcd60e51b815260040161067890613da6565b600b805460ff191690556004546001600160a01b031661155057505f611b06565b60048054604051637376909960e01b815233928101929092525f916001600160a01b0390911690637376909990602401602060405180830381865afa15801561159b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115bf9190614071565b6001600160601b0316146116245760405162461bcd60e51b815260206004820152602660248201527f564149206d696e74206f6e6c7920616c6c6f77656420696e2074686520636f726044820152651948141bdbdb60d21b6064820152608401610678565b61162d82613421565b611635612a3b565b61163d6124c9565b601654604080516318160ddd60e01b815290515f9233926001600160a01b0390911691849183916318160ddd916004808201926020929091908290030181865afa15801561168d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b19190613dca565b90505f6116be8288613467565b90506013548111156117055760405162461bcd60e51b815260206004820152601060248201526f1b5a5b9d0818d85c081c995858da195960821b6044820152606401610678565b61170e8461349c565b5f61171885610a5f565b909650905085156117755760405162461bcd60e51b815260206004820152602160248201527f636f756c64206e6f7420636f6d70757465206d696e7461626c6520616d6f756e6044820152601d60fa1b6064820152608401610678565b808811156117c55760405162461bcd60e51b815260206004820152601960248201527f6d696e74696e67206d6f7265207468616e20616c6c6f776564000000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b03888116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611812573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118369190613dca565b90508015611896575f6118488761224f565b90505f6118558284613628565b6001600160a01b0389165f9081526012602052604090205490915061187a9082613467565b6001600160a01b0389165f908152601260205260409020555090505b5f6118a1828b613467565b6004805460405163fd51a3ad60e01b81526001600160a01b038b81169382019390935260248101849052929350169063fd51a3ad906044016020604051808303815f875af11580156118f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119199190613dca565b975087156119615760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f600a545f14611a41575f61198961197b8d600a54613661565b670de0b6b3a76400006136a2565b90506119958c82613628565b6009546040516340c10f1960e01b81526001600160a01b039182166004820152602481018490529193508916906340c10f19906044015f604051808303815f87803b1580156119e2575f80fd5b505af11580156119f4573d5f803e3d5ffd5b5050604080516001600160a01b038d168152602081018590527fb0715a6d41a37c1b0672c22c09a31a0642c1fb3f9efa2d5fd5c6d2d891ee78c6935001905060405180910390a150611a44565b50895b6040516340c10f1960e01b81526001600160a01b038981166004830152602482018390528816906340c10f19906044015f604051808303815f87803b158015611a8b575f80fd5b505af1158015611a9d573d5f803e3d5ffd5b5050600f546001600160a01b038b165f818152601160209081526040918290209390935580519182529181018590527e2e68ab1600fc5e7290e2ceaa79e2f86b4dbaca84a48421e167e0b40409218a935001905060405180910390a15f99505050505050505050505b600b805460ff19166001179055919050565b5f546001600160a01b03163314611b415760405162461bcd60e51b815260040161067890613df5565b601654604080516001600160a01b03928316815291831660208301527fe45150fb0a88e2274ecbca05ddde9925dd64b6e126ae0fa23ee2d42e668a49d3910160405180910390a1601680546001600160a01b0319166001600160a01b0392909216919091179055565b5f611be96040518060400160405280601b81526020017f746f67676c654f6e6c795072696d65486f6c6465724d696e74282900000000008152506130d6565b601554600160a01b900460ff16158015611c0c57506015546001600160a01b0316155b15611c175750600290565b60155460408051600160a01b90920460ff16158015835260208301527f8efa7b6021d602e0cdef814b7435609ee40deb2a0352ca676d10045750516a5f910160405180910390a16015805460ff60a01b198116600160a01b9182900460ff16159091021790555f905090565b5f805f805f611c918761224f565b600480546040516315e3f14f60e11b81526001600160a01b038b8116938201939093529293505f92611d0e9285921690632bc7e29e90602401602060405180830381865afa158015611ce5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d099190613dca565b613401565b90935090505f836003811115611d2657611d26613de1565b14611d435760405162461bcd60e51b81526004016106789061408a565b6001600160a01b0388165f90815260126020526040902054611d659082613387565b90935090505f836003811115611d7d57611d7d613de1565b14611d9a5760405162461bcd60e51b81526004016106789061408a565b6001600160a01b0388165f908152601260205260408120548290848a10611dff57611dc58585613401565b90965092505f866003811115611ddd57611ddd613de1565b14611dfa5760405162461bcd60e51b81526004016106789061408a565b61210f565b5f611e128b670de0b6b3a764000061332b565b90975090505f876003811115611e2a57611e2a613de1565b14611e775760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b611e818187613368565b90975090505f876003811115611e9957611e99613de1565b14611ee65760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b5f611ef18787613401565b90985090505f886003811115611f0957611f09613de1565b14611f625760405162461bcd60e51b8152602060048201526024808201527f5641495f4d494e5445445f414d4f554e545f43414c43554c4154494f4e5f46416044820152631253115160e21b6064820152608401610678565b611f6c818361332b565b90985094505f886003811115611f8457611f84613de1565b14611fa15760405162461bcd60e51b81526004016106789061408a565b611fb385670de0b6b3a7640000613368565b90985094505f886003811115611fcb57611fcb613de1565b14611fe85760405162461bcd60e51b81526004016106789061408a565b611ff2868361332b565b90985093505f88600381111561200a5761200a613de1565b146120275760405162461bcd60e51b8152600401610678906140cc565b61203984670de0b6b3a7640000613368565b90985093505f88600381111561205157612051613de1565b1461206e5760405162461bcd60e51b8152600401610678906140cc565b6001600160a01b038d165f90815260126020526040902054612090908361332b565b90985092505f8860038111156120a8576120a8613de1565b146120c55760405162461bcd60e51b81526004016106789061411a565b6120d783670de0b6b3a7640000613368565b90985092505f8860038111156120ef576120ef613de1565b1461210c5760405162461bcd60e51b81526004016106789061411a565b50505b919750955093505050509250925092565b600b545f90819060ff166121465760405162461bcd60e51b815260040161067890613da6565b600b805460ff1916905561215a3384613183565b91509150600b805460ff191660011790559092909150565b5f546001600160a01b0316331461219b5760405162461bcd60e51b815260040161067890613df5565b6121a481613088565b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f4df62dd7d9cc4f480a167c19c616ae5d5bb40db6d0c2bc66dba57068225f00d891016107d5565b5f806122086125c3565b90505f8061221a8363042d5600613368565b90925090505f82600381111561223257612232613de1565b146115045760405162461bcd60e51b81526004016106789061415e565b600480546040516315e3f14f60e11b81526001600160a01b03848116938201939093525f9283928392839290911690632bc7e29e90602401602060405180830381865afa1580156122a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122c69190613dca565b6001600160a01b0386165f90815260126020526040812054919250806122ec8484613401565b90965091505f86600381111561230457612304613de1565b146123215760405162461bcd60e51b81526004016106789061419f565b612330600f54611d098a610a2a565b90965094505f86600381111561234857612348613de1565b146123655760405162461bcd60e51b81526004016106789061419f565b61236f858361332b565b90965090505f86600381111561238757612387613de1565b146123a45760405162461bcd60e51b81526004016106789061419f565b6123b681670de0b6b3a7640000613368565b90965090505f8660038111156123ce576123ce613de1565b146123eb5760405162461bcd60e51b81526004016106789061419f565b6123f58482613387565b90965093505f86600381111561240d5761240d613de1565b1461242a5760405162461bcd60e51b81526004016106789061419f565b50919695505050505050565b5f546001600160a01b0316331461245f5760405162461bcd60e51b815260040161067890613df5565b600f54156124a55760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610678565b670de0b6b3a7640000600f55436010555f19601355600b805460ff19166001179055565b5f806124e36124d66121fe565b60105461125890436141fc565b90925090505f8260038111156124fb576124fb613de1565b146125485760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b61255481600f54613387565b90925090505f82600381111561256c5761256c613de1565b146125b95760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b600f555043601055565b60048054604080516307dc0d1d60e41b815290515f9384936001600160a01b031692637dc0d1d092818301926020928290030181865afa158015612609573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061262d9190613e1d565b90505f80600c54111561280c57600d5415612802575f826001600160a01b031663fc57d4df6126646016546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156126a6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126ca9190613dca565b905080670de0b6b3a764000011156127f7575f806126f0670de0b6b3a764000084613401565b90945091505f84600381111561270857612708613de1565b146127255760405162461bcd60e51b81526004016106789061415e565b61273182600d5461332b565b90945091505f84600381111561274957612749613de1565b146127665760405162461bcd60e51b81526004016106789061415e565b61277882670de0b6b3a7640000613368565b90945091505f84600381111561279057612790613de1565b146127ad5760405162461bcd60e51b81526004016106789061415e565b6127b982600c54613387565b90945090505f8460038111156127d1576127d1613de1565b146127ee5760405162461bcd60e51b81526004016106789061415e565b95945050505050565b600c54935050505090565b600c549250505090565b5f9250505090565b5f546001600160a01b0316331461283d5760405162461bcd60e51b815260040161067890613df5565b601554604080516001600160a01b03928316815291831660208301527ffb26401242c61b503dd09c29da64a5d4f451549f574b882a40bcdc64ee68b83c910160405180910390a1601580546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b03163314806128c957506008546001600160a01b031633145b6128e0576128d960016017612ae8565b9050611504565b670de0b6b3a764000082106129375760405162461bcd60e51b815260206004820152601d60248201527f74726561737572792070657263656e7420636170206f766572666c6f770000006044820152606401610678565b6008805460098054600a80546001600160a01b03198086166001600160a01b038c81169182179098559084168a8816179094559087905560408051948616808652602086019490945292949091169290917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e8910160405180910390a1604080516001600160a01b038085168252881660208201527f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac910160405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a1505f9695505050505050565b600480546040805163084bf5ab60e31b815290516001600160a01b039092169263425fad589282820192602092908290030181865afa158015612a80573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa49190613e4c565b15612ae65760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610678565b565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836006811115612b1c57612b1c613de1565b836017811115612b2e57612b2e613de1565b6040805192835260208301919091525f9082015260600160405180910390a182600681111561150457611504613de1565b6004545f9081906001600160a01b03161561307f57612b7c6124c9565b60048054604051632fe3f38f60e11b815230928101929092526001600160a01b03858116602484015288811660448401528781166064840152608483018790525f92911690635fc7e71e9060a4016020604051808303815f875af1158015612be6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c0a9190613dca565b90508015612c2a57612c1f6002600a836136d4565b5f925092505061307f565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c67573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c8b9190613dca565b14612c9c57612c1f60026009612ae8565b866001600160a01b0316866001600160a01b031603612cc157612c1f6002600f612ae8565b845f03612cd457612c1f6002600d612ae8565b5f198503612ce857612c1f6002600c612ae8565b5f80612cf5898989613753565b90925090508115612d2957612d1c826006811115612d1557612d15613de1565b6010612ae8565b5f9450945050505061307f565b6004805460405163a78dc77560e01b81526001600160a01b0389811693820193909352602481018490525f928392169063a78dc775906044016040805180830381865afa158015612d7c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da09190613f8b565b90925090508115612e195760405162461bcd60e51b815260206004820152603760248201527f5641495f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c60448201527f4154455f414d4f554e545f5345495a455f4641494c45440000000000000000006064820152608401610678565b6040516370a0823160e01b81526001600160a01b038b811660048301528291908a16906370a0823190602401602060405180830381865afa158015612e60573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e849190613dca565b1015612ed25760405162461bcd60e51b815260206004820152601c60248201527f5641495f4c49515549444154455f5345495a455f544f4f5f4d554348000000006044820152606401610678565b60405163b2a02ff160e01b81526001600160a01b038c811660048301528b81166024830152604482018390525f91908a169063b2a02ff1906064016020604051808303815f875af1158015612f29573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613dca565b90508015612f945760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610678565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f42d401f96718a0c42e5cea8108973f0022677b7e2e5f4ee19851b2de7a0394e79181900360a00190a1600480546040516347ef3b3b60e01b815230928101929092526001600160a01b038b811660248401528e811660448401528d811660648401526084830187905260a4830185905216906347ef3b3b9060c4015f604051808303815f87803b158015613056575f80fd5b505af1158015613068573d5f803e3d5ffd5b505f9250613074915050565b975092955050505050505b94509492505050565b6001600160a01b0381166109ca5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610678565b6014546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90613108903390859060040161423d565b602060405180830381865afa158015613123573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131479190613e4c565b6109ca5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610678565b6004545f9081906001600160a01b03166131a157505f9050806131ca565b6131aa83613421565b6131b2612a3b565b6131ba6124c9565b6131c5338585613753565b915091505b9250929050565b5f6131e760405180602001604052805f81525090565b5f806131f9865f0151865f015161332b565b90925090505f82600381111561321157613211613de1565b1461322f575060408051602081019091525f815290925090506131ca565b5f8061324d6132476002670de0b6b3a7640000614260565b84613387565b90925090505f82600381111561326557613265613de1565b14613287578160405180602001604052805f81525095509550505050506131ca565b5f8061329b83670de0b6b3a7640000613368565b90925090505f8260038111156132b3576132b3613de1565b146132c0576132c061427f565b60408051602081019091529081525f9a909950975050505050505050565b5f805f806132ec8686613a99565b90925090505f82600381111561330457613304613de1565b14613314575091505f90506131ca565b5f61331e82613b0e565b9350935050509250929050565b5f80835f0361333e57505f9050806131ca565b8383028361334c8683614260565b1461335e5760025f92509250506131ca565b5f925090506131ca565b5f80825f0361337c5750600190505f6131ca565b5f6131c58486614260565b5f8083830184811061339d575f925090506131ca565b60025f92509250506131ca565b5f805f806133b88787613a99565b90925090505f8260038111156133d0576133d0613de1565b146133e0575091505f90506133f9565b6133f26133ec82613b0e565b86613387565b9350935050505b935093915050565b5f8083831161341657505f90508183036131ca565b50600390505f6131ca565b5f81116109ca5760405162461bcd60e51b8152602060048201526014602482015273616d6f756e742063616e2774206265207a65726f60601b6044820152606401610678565b5f6115048383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250613b25565b5f60045f9054906101000a90046001600160a01b03166001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135119190613e1d565b60048054604051632aff3bff60e21b81526001600160a01b03868116938201939093529293505f9291169063abfceffc906024015f60405180830381865afa15801561355f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526135869190810190613e84565b80519091505f5b8181101561362157836001600160a01b031663a9c3cab18483815181106135b6576135b6613f44565b60200260200101516040518263ffffffff1660e01b81526004016135e991906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015613600575f80fd5b505af1158015613612573d5f803e3d5ffd5b5050505080600101905061358d565b5050505050565b5f6115048383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250613b5e565b5f61150483836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250613b8c565b5f61150483836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613bdc565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084600681111561370857613708613de1565b84601781111561371a5761371a613de1565b604080519283526020830191909152810184905260600160405180910390a183600681111561374b5761374b613de1565b949350505050565b5f805f805f6137628787611c83565b601654604051632770a7eb60e21b81526001600160a01b038d811660048301526024820186905294975092955090935091909116908190639dc29fac906044015f604051808303815f87803b1580156137b9575f80fd5b505af11580156137cb573d5f803e3d5ffd5b5050600e546040516323b872dd60e01b81526001600160a01b038d811660048301529182166024820152604481018790525f935090841691506323b872dd906064016020604051808303815f875af1158015613829573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061384d9190613e4c565b90506001811515146138a15760405162461bcd60e51b815260206004820152601a60248201527f6661696c656420746f207472616e7366657220564149206665650000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa1580156138ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139129190613dca565b90505f6139286139228389613628565b86613628565b6001600160a01b038c165f9081526012602052604090205490915061394d9086613628565b6001600160a01b03808d165f818152601260205260408082209490945560048054945163fd51a3ad60e01b81529081019290925260248201859052929091169063fd51a3ad906044016020604051808303815f875af11580156139b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139d69190613dca565b90508015613a1e5760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f613a298989613467565b90507f1db858e6f7e1a0d5e92c10c6507d42b3dabfe0a4867fe90c5a14d9963662ef7e8e8e83604051613a7d939291906001600160a01b039384168152919092166020820152604081019190915260600190565b60405180910390a15f9e909d509b505050505050505050505050565b5f613aaf60405180602001604052805f81525090565b5f80613abe865f01518661332b565b90925090505f826003811115613ad657613ad6613de1565b14613af4575060408051602081019091525f815290925090506131ca565b60408051602081019091529081525f969095509350505050565b80515f90610a5990670de0b6b3a764000090614260565b5f80613b318486614293565b90508285821015613b555760405162461bcd60e51b815260040161067891906142a6565b50949350505050565b5f8184841115613b815760405162461bcd60e51b815260040161067891906142a6565b5061374b83856141fc565b5f831580613b98575082155b15613ba457505f611504565b5f613baf84866142b8565b905083613bbc8683614260565b148390613b555760405162461bcd60e51b815260040161067891906142a6565b5f8183613bfc5760405162461bcd60e51b815260040161067891906142a6565b5061374b8385614260565b604080516101c081019091525f808252602082019081526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001613c6660405180602001604052805f81525090565b8152602001613c8060405180602001604052805f81525090565b8152602001613c9a60405180602001604052805f81525090565b8152602001613cb460405180602001604052805f81525090565b905290565b6001600160a01b03811681146109ca575f80fd5b5f805f60608486031215613cdf575f80fd5b8335613cea81613cb9565b9250602084013591506040840135613d0181613cb9565b809150509250925092565b5f60208284031215613d1c575f80fd5b813561150481613cb9565b5f60208284031215613d37575f80fd5b5035919050565b5f8060408385031215613d4f575f80fd5b8235613d5a81613cb9565b946020939093013593505050565b5f805f60608486031215613d7a575f80fd5b8335613d8581613cb9565b92506020840135613d9581613cb9565b929592945050506040919091013590565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b5f60208284031215613dda575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b6020808252600e908201526d37b7363c9030b236b4b71031b0b760911b604082015260600190565b5f60208284031215613e2d575f80fd5b815161150481613cb9565b80518015158114613e47575f80fd5b919050565b5f60208284031215613e5c575f80fd5b61150482613e38565b634e487b7160e01b5f52604160045260245ffd5b8051613e4781613cb9565b5f6020808385031215613e95575f80fd5b825167ffffffffffffffff80821115613eac575f80fd5b818501915085601f830112613ebf575f80fd5b815181811115613ed157613ed1613e65565b8060051b604051601f19603f83011681018181108582111715613ef657613ef6613e65565b604052918252848201925083810185019188831115613f13575f80fd5b938501935b82851015613f3857613f2985613e79565b84529385019392850192613f18565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215613f6b575f80fd5b505082516020840151604085015160609095015191969095509092509050565b5f8060408385031215613f9c575f80fd5b505080516020909101519092909150565b80516001600160601b0381168114613e47575f80fd5b5f805f805f805f60e0888a031215613fd9575f80fd5b613fe288613e38565b965060208801519550613ff760408901613e38565b9450606088015193506080880151925061401360a08901613fad565b915061402160c08901613e38565b905092959891949750929550565b60208082526022908201527f5641495f4d494e545f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b5f60208284031215614081575f80fd5b61150482613fad565b60208082526022908201527f5641495f4255524e5f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b6020808252602e908201527f5641495f43555252454e545f494e5445524553545f414d4f554e545f43414c4360408201526d155310551253d397d1905253115160921b606082015260800190565b60208082526024908201527f5641495f504153545f494e5445524553545f43414c43554c4154494f4e5f46416040820152631253115160e21b606082015260800190565b60208082526021908201527f5641495f52455041595f524154455f43414c43554c4154494f4e5f4641494c456040820152601160fa1b606082015260800190565b60208082526029908201527f5641495f544f54414c5f52455041595f414d4f554e545f43414c43554c41544960408201526813d397d1905253115160ba1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a5957610a596141e8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f9061374b9083018461420f565b5f8261427a57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52600160045260245ffd5b80820180821115610a5957610a596141e8565b602081525f611504602083018461420f565b8082028115828204841417610a5957610a596141e856fea26469706673582212206eb9e4fce6049c92043fdf95235dced95a1f7fd5ce40415c966d53a8db9d82ec64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061028b575f3560e01c8063691e45ac11610161578063b49b1005116100ca578063d24febad11610084578063d24febad146105a1578063e44e6168146105b4578063ee1fa41e146105fa578063f20fd8f41461060e578063f7260d3e1461062d578063f851a44014610640575f80fd5b8063b49b100514610547578063b9ee87261461054f578063c32094c714610557578063c5f956af1461056a578063c7ee005e1461057d578063cbeb2b2814610590575f80fd5b806378c2f9221161011b57806378c2f922146104de5780637a37c5d0146104f15780638129fc1c14610510578063b06bb42614610518578063b2b481bc1461052b578063b2eafc3914610534575f80fd5b8063691e45ac1461046f5780636fe74a211461049d578063718da7ee146104b0578063741de148146104c357806375c3de43146104cd57806376c71ca1146104d5575f80fd5b80633785d1d6116102035780635ce73240116101bd5780635ce732401461040c5780635fe3b5671461041557806360c954ef1461042857806361b3311c146104455780636509795414610458578063657bdf9414610467575f80fd5b80633785d1d6146103a45780633b5a0a64146103b75780633b72fbef146103ca5780634070a0c9146103d35780634576b5db146103e65780634712ee7d146103f9575f80fd5b80631d08837b116102545780631d08837b146103265780631d504dc6146103395780631f040ff51461034c578063234f89771461035f57806324650602146103725780632678224714610391575f80fd5b80623b58841461028f57806304ef9d58146102bf57806311b3d5e7146102d657806313007d55146102fe57806319129e5a14610311575b5f80fd5b6002546102a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102c8600a5481565b6040519081526020016102b6565b6102e96102e4366004613ccd565b610652565b604080519283526020830191909152016102b6565b6014546102a2906001600160a01b031681565b61032461031f366004613d0c565b61074d565b005b610324610334366004613d27565b6107e1565b610324610347366004613d0c565b610854565b6102e961035a366004613d3e565b6109cd565b6102c861036d366004613d0c565b610a2a565b6102c8610380366004613d0c565b60076020525f908152604090205481565b6001546102a2906001600160a01b031681565b6102e96103b2366004613d0c565b610a5f565b6103246103c5366004613d27565b6113a1565b6102c8600c5481565b6103246103e1366004613d27565b611415565b6102c86103f4366004613d0c565b611487565b6102c8610407366004613d27565b61150b565b6102c8600d5481565b6004546102a2906001600160a01b031681565b6006546104359060ff1681565b60405190151581526020016102b6565b610324610453366004613d0c565b611b18565b6102c8670de0b6b3a764000081565b6102c8611baa565b61048261047d366004613d3e565b611c83565b604080519384526020840192909252908201526060016102b6565b6102e96104ab366004613d27565b612120565b6103246104be366004613d0c565b612172565b63042d56006102c8565b6102c86121fe565b6102c860135481565b6102c86104ec366004613d0c565b61224f565b6104f85f81565b6040516001600160601b0390911681526020016102b6565b610324612436565b6003546102a2906001600160a01b031681565b6102c8600f5481565b6008546102a2906001600160a01b031681565b6103246124c9565b6102c86125c3565b610324610565366004613d0c565b612814565b6009546102a2906001600160a01b031681565b6015546102a2906001600160a01b031681565b6016546001600160a01b03166102a2565b6102c86105af366004613d68565b6128a6565b6005546105d6906001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016102b6565b60155461043590600160a01b900460ff1681565b6102c861061c366004613d0c565b60126020525f908152604090205481565b600e546102a2906001600160a01b031681565b5f546102a2906001600160a01b031681565b600b545f90819060ff166106815760405162461bcd60e51b815260040161067890613da6565b60405180910390fd5b600b805460ff19169055610693612a3b565b5f836001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303815f875af11580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190613dca565b905080156107245761071981600681111561071257610712613de1565b6008612ae8565b5f9250925050610736565b61073033878787612b5f565b92509250505b600b805460ff191660011790559094909350915050565b5f546001600160a01b031633146107765760405162461bcd60e51b815260040161067890613df5565b61077f81613088565b601480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd491015b60405180910390a15050565b6108166040518060400160405280601481526020017373657442617365526174652875696e743235362960601b8152506130d6565b600c80549082905560408051828152602081018490527fc84c32795e68685ec107b0e94ae126ef464095f342c7e2e0fec06a23d2e8677e91016107d5565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b49190613e1d565b6001600160a01b0316336001600160a01b0316146109245760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610678565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610961573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109859190613dca565b156109ca5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610678565b50565b600b545f90819060ff166109f35760405162461bcd60e51b815260040161067890613da6565b600b805460ff19169055610a0684613088565b610a108484613183565b91509150600b805460ff1916600117905590939092509050565b6001600160a01b0381165f90815260116020526040812054808203610a595750670de0b6b3a764000092915050565b92915050565b6015545f908190600160a01b900460ff168015610ae55750601554604051630e3da90d60e21b81526001600160a01b038581166004830152909116906338f6a43490602401602060405180830381865afa158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae39190613e4c565b155b15610af5576002935f9350915050565b60048054604051632aff3bff60e21b81526001600160a01b03868116938201939093525f929091169063abfceffc906024015f60405180830381865afa158015610b41573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b689190810190613e84565b90505f60045f9054906101000a90046001600160a01b03166001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bdf9190613e1d565b9050610be9613c07565b82515f9081905b808210156110e557858281518110610c0a57610c0a613f44565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038b811660048301529091169063c37f68e290602401608060405180830381865afa158015610c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613f58565b60e088015260c087015260a086015280855215610ca75760035b995f9950975050505050505050565b60405180602001604052808560e00151815250846101400181905250846001600160a01b03166388142b6b878481518110610ce457610ce4613f44565b60200260200101516040518263ffffffff1660e01b8152600401610d1791906001600160a01b0391909116815260200190565b6040805180830381865afa158015610d31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d559190613f8b565b61012086015261010085018190521580610d725750610120840151155b15610d7e576004610c98565b604080516020808201835261010087015182526101608701918252825190810190925261012086015182526101808601919091526101408501519051610dc491906131d1565b85602001866101a001829052826003811115610de257610de2613de1565b6003811115610df357610df3613de1565b9052505f905084602001516003811115610e0f57610e0f613de1565b14610e1b576005610c98565b610e2e846101a001518560a001516132de565b6060860181905260208601826003811115610e4b57610e4b613de1565b6003811115610e5c57610e5c613de1565b9052505f905084602001516003811115610e7857610e78613de1565b14610e84576005610c98565b60045486515f916001600160a01b031690638e8f294b90899086908110610ead57610ead613f44565b60200260200101516040518263ffffffff1660e01b8152600401610ee091906001600160a01b0391909116815260200190565b60e060405180830381865afa158015610efb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f1f9190613fc3565b5050505050915050610f3585606001518261332b565b6060870181905260208701826003811115610f5257610f52613de1565b6003811115610f6357610f63613de1565b9052505f905085602001516003811115610f7f57610f7f613de1565b14610f975760055b9a5f9a5098505050505050505050565b610fad8560600151670de0b6b3a7640000613368565b6060870181905260208701826003811115610fca57610fca613de1565b6003811115610fdb57610fdb613de1565b9052505f905085602001516003811115610ff757610ff7613de1565b14611003576005610f87565b61101585604001518660600151613387565b604087018190526020870182600381111561103257611032613de1565b600381111561104357611043613de1565b9052505f90508560200151600381111561105f5761105f613de1565b1461106b576005610f87565b6110838561018001518660c0015187608001516133aa565b60808701819052602087018260038111156110a0576110a0613de1565b60038111156110b1576110b1613de1565b9052505f9050856020015160038111156110cd576110cd613de1565b146110d9576005610f87565b50600190910190610bf0565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611132573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111569190613dca565b90505f811561116b576111688b61224f565b90505b611179866080015182613387565b608088018190526020880182600381111561119657611196613de1565b60038111156111a7576111a7613de1565b9052505f9050866020015160038111156111c3576111c3613de1565b146111dc5760055b9b5f9b509950505050505050505050565b61125d866040015160045f9054906101000a90046001600160a01b03166001600160a01b031663bec04f726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611234573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112589190613dca565b61332b565b8760200181975082600381111561127657611276613de1565b600381111561128757611287613de1565b9052505f9050866020015160038111156112a3576112a3613de1565b146112c05760405162461bcd60e51b81526004016106789061402f565b6112cc85612710613368565b876020018197508260038111156112e5576112e5613de1565b60038111156112f6576112f6613de1565b9052505f90508660200151600381111561131257611312613de1565b1461132f5760405162461bcd60e51b81526004016106789061402f565b61133d858760800151613401565b8760200181975082600381111561135657611356613de1565b600381111561136757611367613de1565b9052505f90508660200151600381111561138357611383613de1565b1461138f5760026111cb565b5f9b949a509398505050505050505050565b6113d760405180604001604052806015815260200174736574466c6f6174526174652875696e743235362960581b8152506130d6565b600d80549082905560408051828152602081018490527f546fb35dbbd92233aecc22b5a11a6791e5db7ec14f62e49cbac2a10c0437f56191016107d5565b611449604051806040016040528060138152602001727365744d696e744361702875696e743235362960681b8152506130d6565b601380549082905560408051828152602081018490527f43862b3eea2df8fce70329f3f84cbcad220f47a73be46c5e00df25165a6e169591016107d5565b5f80546001600160a01b031633146114a557610a5960016002612ae8565b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d910160405180910390a15f5b9392505050565b600b545f9060ff1661152f5760405162461bcd60e51b815260040161067890613da6565b600b805460ff191690556004546001600160a01b031661155057505f611b06565b60048054604051637376909960e01b815233928101929092525f916001600160a01b0390911690637376909990602401602060405180830381865afa15801561159b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115bf9190614071565b6001600160601b0316146116245760405162461bcd60e51b815260206004820152602660248201527f564149206d696e74206f6e6c7920616c6c6f77656420696e2074686520636f726044820152651948141bdbdb60d21b6064820152608401610678565b61162d82613421565b611635612a3b565b61163d6124c9565b601654604080516318160ddd60e01b815290515f9233926001600160a01b0390911691849183916318160ddd916004808201926020929091908290030181865afa15801561168d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b19190613dca565b90505f6116be8288613467565b90506013548111156117055760405162461bcd60e51b815260206004820152601060248201526f1b5a5b9d0818d85c081c995858da195960821b6044820152606401610678565b61170e8461349c565b5f61171885610a5f565b909650905085156117755760405162461bcd60e51b815260206004820152602160248201527f636f756c64206e6f7420636f6d70757465206d696e7461626c6520616d6f756e6044820152601d60fa1b6064820152608401610678565b808811156117c55760405162461bcd60e51b815260206004820152601960248201527f6d696e74696e67206d6f7265207468616e20616c6c6f776564000000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b03888116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611812573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118369190613dca565b90508015611896575f6118488761224f565b90505f6118558284613628565b6001600160a01b0389165f9081526012602052604090205490915061187a9082613467565b6001600160a01b0389165f908152601260205260409020555090505b5f6118a1828b613467565b6004805460405163fd51a3ad60e01b81526001600160a01b038b81169382019390935260248101849052929350169063fd51a3ad906044016020604051808303815f875af11580156118f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119199190613dca565b975087156119615760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f600a545f14611a41575f61198961197b8d600a54613661565b670de0b6b3a76400006136a2565b90506119958c82613628565b6009546040516340c10f1960e01b81526001600160a01b039182166004820152602481018490529193508916906340c10f19906044015f604051808303815f87803b1580156119e2575f80fd5b505af11580156119f4573d5f803e3d5ffd5b5050604080516001600160a01b038d168152602081018590527fb0715a6d41a37c1b0672c22c09a31a0642c1fb3f9efa2d5fd5c6d2d891ee78c6935001905060405180910390a150611a44565b50895b6040516340c10f1960e01b81526001600160a01b038981166004830152602482018390528816906340c10f19906044015f604051808303815f87803b158015611a8b575f80fd5b505af1158015611a9d573d5f803e3d5ffd5b5050600f546001600160a01b038b165f818152601160209081526040918290209390935580519182529181018590527e2e68ab1600fc5e7290e2ceaa79e2f86b4dbaca84a48421e167e0b40409218a935001905060405180910390a15f99505050505050505050505b600b805460ff19166001179055919050565b5f546001600160a01b03163314611b415760405162461bcd60e51b815260040161067890613df5565b601654604080516001600160a01b03928316815291831660208301527fe45150fb0a88e2274ecbca05ddde9925dd64b6e126ae0fa23ee2d42e668a49d3910160405180910390a1601680546001600160a01b0319166001600160a01b0392909216919091179055565b5f611be96040518060400160405280601b81526020017f746f67676c654f6e6c795072696d65486f6c6465724d696e74282900000000008152506130d6565b601554600160a01b900460ff16158015611c0c57506015546001600160a01b0316155b15611c175750600290565b60155460408051600160a01b90920460ff16158015835260208301527f8efa7b6021d602e0cdef814b7435609ee40deb2a0352ca676d10045750516a5f910160405180910390a16015805460ff60a01b198116600160a01b9182900460ff16159091021790555f905090565b5f805f805f611c918761224f565b600480546040516315e3f14f60e11b81526001600160a01b038b8116938201939093529293505f92611d0e9285921690632bc7e29e90602401602060405180830381865afa158015611ce5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d099190613dca565b613401565b90935090505f836003811115611d2657611d26613de1565b14611d435760405162461bcd60e51b81526004016106789061408a565b6001600160a01b0388165f90815260126020526040902054611d659082613387565b90935090505f836003811115611d7d57611d7d613de1565b14611d9a5760405162461bcd60e51b81526004016106789061408a565b6001600160a01b0388165f908152601260205260408120548290848a10611dff57611dc58585613401565b90965092505f866003811115611ddd57611ddd613de1565b14611dfa5760405162461bcd60e51b81526004016106789061408a565b61210f565b5f611e128b670de0b6b3a764000061332b565b90975090505f876003811115611e2a57611e2a613de1565b14611e775760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b611e818187613368565b90975090505f876003811115611e9957611e99613de1565b14611ee65760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b5f611ef18787613401565b90985090505f886003811115611f0957611f09613de1565b14611f625760405162461bcd60e51b8152602060048201526024808201527f5641495f4d494e5445445f414d4f554e545f43414c43554c4154494f4e5f46416044820152631253115160e21b6064820152608401610678565b611f6c818361332b565b90985094505f886003811115611f8457611f84613de1565b14611fa15760405162461bcd60e51b81526004016106789061408a565b611fb385670de0b6b3a7640000613368565b90985094505f886003811115611fcb57611fcb613de1565b14611fe85760405162461bcd60e51b81526004016106789061408a565b611ff2868361332b565b90985093505f88600381111561200a5761200a613de1565b146120275760405162461bcd60e51b8152600401610678906140cc565b61203984670de0b6b3a7640000613368565b90985093505f88600381111561205157612051613de1565b1461206e5760405162461bcd60e51b8152600401610678906140cc565b6001600160a01b038d165f90815260126020526040902054612090908361332b565b90985092505f8860038111156120a8576120a8613de1565b146120c55760405162461bcd60e51b81526004016106789061411a565b6120d783670de0b6b3a7640000613368565b90985092505f8860038111156120ef576120ef613de1565b1461210c5760405162461bcd60e51b81526004016106789061411a565b50505b919750955093505050509250925092565b600b545f90819060ff166121465760405162461bcd60e51b815260040161067890613da6565b600b805460ff1916905561215a3384613183565b91509150600b805460ff191660011790559092909150565b5f546001600160a01b0316331461219b5760405162461bcd60e51b815260040161067890613df5565b6121a481613088565b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f4df62dd7d9cc4f480a167c19c616ae5d5bb40db6d0c2bc66dba57068225f00d891016107d5565b5f806122086125c3565b90505f8061221a8363042d5600613368565b90925090505f82600381111561223257612232613de1565b146115045760405162461bcd60e51b81526004016106789061415e565b600480546040516315e3f14f60e11b81526001600160a01b03848116938201939093525f9283928392839290911690632bc7e29e90602401602060405180830381865afa1580156122a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122c69190613dca565b6001600160a01b0386165f90815260126020526040812054919250806122ec8484613401565b90965091505f86600381111561230457612304613de1565b146123215760405162461bcd60e51b81526004016106789061419f565b612330600f54611d098a610a2a565b90965094505f86600381111561234857612348613de1565b146123655760405162461bcd60e51b81526004016106789061419f565b61236f858361332b565b90965090505f86600381111561238757612387613de1565b146123a45760405162461bcd60e51b81526004016106789061419f565b6123b681670de0b6b3a7640000613368565b90965090505f8660038111156123ce576123ce613de1565b146123eb5760405162461bcd60e51b81526004016106789061419f565b6123f58482613387565b90965093505f86600381111561240d5761240d613de1565b1461242a5760405162461bcd60e51b81526004016106789061419f565b50919695505050505050565b5f546001600160a01b0316331461245f5760405162461bcd60e51b815260040161067890613df5565b600f54156124a55760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610678565b670de0b6b3a7640000600f55436010555f19601355600b805460ff19166001179055565b5f806124e36124d66121fe565b60105461125890436141fc565b90925090505f8260038111156124fb576124fb613de1565b146125485760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b61255481600f54613387565b90925090505f82600381111561256c5761256c613de1565b146125b95760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b600f555043601055565b60048054604080516307dc0d1d60e41b815290515f9384936001600160a01b031692637dc0d1d092818301926020928290030181865afa158015612609573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061262d9190613e1d565b90505f80600c54111561280c57600d5415612802575f826001600160a01b031663fc57d4df6126646016546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156126a6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126ca9190613dca565b905080670de0b6b3a764000011156127f7575f806126f0670de0b6b3a764000084613401565b90945091505f84600381111561270857612708613de1565b146127255760405162461bcd60e51b81526004016106789061415e565b61273182600d5461332b565b90945091505f84600381111561274957612749613de1565b146127665760405162461bcd60e51b81526004016106789061415e565b61277882670de0b6b3a7640000613368565b90945091505f84600381111561279057612790613de1565b146127ad5760405162461bcd60e51b81526004016106789061415e565b6127b982600c54613387565b90945090505f8460038111156127d1576127d1613de1565b146127ee5760405162461bcd60e51b81526004016106789061415e565b95945050505050565b600c54935050505090565b600c549250505090565b5f9250505090565b5f546001600160a01b0316331461283d5760405162461bcd60e51b815260040161067890613df5565b601554604080516001600160a01b03928316815291831660208301527ffb26401242c61b503dd09c29da64a5d4f451549f574b882a40bcdc64ee68b83c910160405180910390a1601580546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b03163314806128c957506008546001600160a01b031633145b6128e0576128d960016017612ae8565b9050611504565b670de0b6b3a764000082106129375760405162461bcd60e51b815260206004820152601d60248201527f74726561737572792070657263656e7420636170206f766572666c6f770000006044820152606401610678565b6008805460098054600a80546001600160a01b03198086166001600160a01b038c81169182179098559084168a8816179094559087905560408051948616808652602086019490945292949091169290917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e8910160405180910390a1604080516001600160a01b038085168252881660208201527f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac910160405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a1505f9695505050505050565b600480546040805163084bf5ab60e31b815290516001600160a01b039092169263425fad589282820192602092908290030181865afa158015612a80573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa49190613e4c565b15612ae65760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610678565b565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836006811115612b1c57612b1c613de1565b836017811115612b2e57612b2e613de1565b6040805192835260208301919091525f9082015260600160405180910390a182600681111561150457611504613de1565b6004545f9081906001600160a01b03161561307f57612b7c6124c9565b60048054604051632fe3f38f60e11b815230928101929092526001600160a01b03858116602484015288811660448401528781166064840152608483018790525f92911690635fc7e71e9060a4016020604051808303815f875af1158015612be6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c0a9190613dca565b90508015612c2a57612c1f6002600a836136d4565b5f925092505061307f565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c67573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c8b9190613dca565b14612c9c57612c1f60026009612ae8565b866001600160a01b0316866001600160a01b031603612cc157612c1f6002600f612ae8565b845f03612cd457612c1f6002600d612ae8565b5f198503612ce857612c1f6002600c612ae8565b5f80612cf5898989613753565b90925090508115612d2957612d1c826006811115612d1557612d15613de1565b6010612ae8565b5f9450945050505061307f565b6004805460405163a78dc77560e01b81526001600160a01b0389811693820193909352602481018490525f928392169063a78dc775906044016040805180830381865afa158015612d7c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da09190613f8b565b90925090508115612e195760405162461bcd60e51b815260206004820152603760248201527f5641495f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c60448201527f4154455f414d4f554e545f5345495a455f4641494c45440000000000000000006064820152608401610678565b6040516370a0823160e01b81526001600160a01b038b811660048301528291908a16906370a0823190602401602060405180830381865afa158015612e60573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e849190613dca565b1015612ed25760405162461bcd60e51b815260206004820152601c60248201527f5641495f4c49515549444154455f5345495a455f544f4f5f4d554348000000006044820152606401610678565b60405163b2a02ff160e01b81526001600160a01b038c811660048301528b81166024830152604482018390525f91908a169063b2a02ff1906064016020604051808303815f875af1158015612f29573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613dca565b90508015612f945760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610678565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f42d401f96718a0c42e5cea8108973f0022677b7e2e5f4ee19851b2de7a0394e79181900360a00190a1600480546040516347ef3b3b60e01b815230928101929092526001600160a01b038b811660248401528e811660448401528d811660648401526084830187905260a4830185905216906347ef3b3b9060c4015f604051808303815f87803b158015613056575f80fd5b505af1158015613068573d5f803e3d5ffd5b505f9250613074915050565b975092955050505050505b94509492505050565b6001600160a01b0381166109ca5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610678565b6014546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90613108903390859060040161423d565b602060405180830381865afa158015613123573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131479190613e4c565b6109ca5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610678565b6004545f9081906001600160a01b03166131a157505f9050806131ca565b6131aa83613421565b6131b2612a3b565b6131ba6124c9565b6131c5338585613753565b915091505b9250929050565b5f6131e760405180602001604052805f81525090565b5f806131f9865f0151865f015161332b565b90925090505f82600381111561321157613211613de1565b1461322f575060408051602081019091525f815290925090506131ca565b5f8061324d6132476002670de0b6b3a7640000614260565b84613387565b90925090505f82600381111561326557613265613de1565b14613287578160405180602001604052805f81525095509550505050506131ca565b5f8061329b83670de0b6b3a7640000613368565b90925090505f8260038111156132b3576132b3613de1565b146132c0576132c061427f565b60408051602081019091529081525f9a909950975050505050505050565b5f805f806132ec8686613a99565b90925090505f82600381111561330457613304613de1565b14613314575091505f90506131ca565b5f61331e82613b0e565b9350935050509250929050565b5f80835f0361333e57505f9050806131ca565b8383028361334c8683614260565b1461335e5760025f92509250506131ca565b5f925090506131ca565b5f80825f0361337c5750600190505f6131ca565b5f6131c58486614260565b5f8083830184811061339d575f925090506131ca565b60025f92509250506131ca565b5f805f806133b88787613a99565b90925090505f8260038111156133d0576133d0613de1565b146133e0575091505f90506133f9565b6133f26133ec82613b0e565b86613387565b9350935050505b935093915050565b5f8083831161341657505f90508183036131ca565b50600390505f6131ca565b5f81116109ca5760405162461bcd60e51b8152602060048201526014602482015273616d6f756e742063616e2774206265207a65726f60601b6044820152606401610678565b5f6115048383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250613b25565b5f60045f9054906101000a90046001600160a01b03166001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135119190613e1d565b60048054604051632aff3bff60e21b81526001600160a01b03868116938201939093529293505f9291169063abfceffc906024015f60405180830381865afa15801561355f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526135869190810190613e84565b80519091505f5b8181101561362157836001600160a01b031663a9c3cab18483815181106135b6576135b6613f44565b60200260200101516040518263ffffffff1660e01b81526004016135e991906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015613600575f80fd5b505af1158015613612573d5f803e3d5ffd5b5050505080600101905061358d565b5050505050565b5f6115048383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250613b5e565b5f61150483836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250613b8c565b5f61150483836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613bdc565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084600681111561370857613708613de1565b84601781111561371a5761371a613de1565b604080519283526020830191909152810184905260600160405180910390a183600681111561374b5761374b613de1565b949350505050565b5f805f805f6137628787611c83565b601654604051632770a7eb60e21b81526001600160a01b038d811660048301526024820186905294975092955090935091909116908190639dc29fac906044015f604051808303815f87803b1580156137b9575f80fd5b505af11580156137cb573d5f803e3d5ffd5b5050600e546040516323b872dd60e01b81526001600160a01b038d811660048301529182166024820152604481018790525f935090841691506323b872dd906064016020604051808303815f875af1158015613829573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061384d9190613e4c565b90506001811515146138a15760405162461bcd60e51b815260206004820152601a60248201527f6661696c656420746f207472616e7366657220564149206665650000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa1580156138ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139129190613dca565b90505f6139286139228389613628565b86613628565b6001600160a01b038c165f9081526012602052604090205490915061394d9086613628565b6001600160a01b03808d165f818152601260205260408082209490945560048054945163fd51a3ad60e01b81529081019290925260248201859052929091169063fd51a3ad906044016020604051808303815f875af11580156139b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139d69190613dca565b90508015613a1e5760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f613a298989613467565b90507f1db858e6f7e1a0d5e92c10c6507d42b3dabfe0a4867fe90c5a14d9963662ef7e8e8e83604051613a7d939291906001600160a01b039384168152919092166020820152604081019190915260600190565b60405180910390a15f9e909d509b505050505050505050505050565b5f613aaf60405180602001604052805f81525090565b5f80613abe865f01518661332b565b90925090505f826003811115613ad657613ad6613de1565b14613af4575060408051602081019091525f815290925090506131ca565b60408051602081019091529081525f969095509350505050565b80515f90610a5990670de0b6b3a764000090614260565b5f80613b318486614293565b90508285821015613b555760405162461bcd60e51b815260040161067891906142a6565b50949350505050565b5f8184841115613b815760405162461bcd60e51b815260040161067891906142a6565b5061374b83856141fc565b5f831580613b98575082155b15613ba457505f611504565b5f613baf84866142b8565b905083613bbc8683614260565b148390613b555760405162461bcd60e51b815260040161067891906142a6565b5f8183613bfc5760405162461bcd60e51b815260040161067891906142a6565b5061374b8385614260565b604080516101c081019091525f808252602082019081526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001613c6660405180602001604052805f81525090565b8152602001613c8060405180602001604052805f81525090565b8152602001613c9a60405180602001604052805f81525090565b8152602001613cb460405180602001604052805f81525090565b905290565b6001600160a01b03811681146109ca575f80fd5b5f805f60608486031215613cdf575f80fd5b8335613cea81613cb9565b9250602084013591506040840135613d0181613cb9565b809150509250925092565b5f60208284031215613d1c575f80fd5b813561150481613cb9565b5f60208284031215613d37575f80fd5b5035919050565b5f8060408385031215613d4f575f80fd5b8235613d5a81613cb9565b946020939093013593505050565b5f805f60608486031215613d7a575f80fd5b8335613d8581613cb9565b92506020840135613d9581613cb9565b929592945050506040919091013590565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b5f60208284031215613dda575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b6020808252600e908201526d37b7363c9030b236b4b71031b0b760911b604082015260600190565b5f60208284031215613e2d575f80fd5b815161150481613cb9565b80518015158114613e47575f80fd5b919050565b5f60208284031215613e5c575f80fd5b61150482613e38565b634e487b7160e01b5f52604160045260245ffd5b8051613e4781613cb9565b5f6020808385031215613e95575f80fd5b825167ffffffffffffffff80821115613eac575f80fd5b818501915085601f830112613ebf575f80fd5b815181811115613ed157613ed1613e65565b8060051b604051601f19603f83011681018181108582111715613ef657613ef6613e65565b604052918252848201925083810185019188831115613f13575f80fd5b938501935b82851015613f3857613f2985613e79565b84529385019392850192613f18565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215613f6b575f80fd5b505082516020840151604085015160609095015191969095509092509050565b5f8060408385031215613f9c575f80fd5b505080516020909101519092909150565b80516001600160601b0381168114613e47575f80fd5b5f805f805f805f60e0888a031215613fd9575f80fd5b613fe288613e38565b965060208801519550613ff760408901613e38565b9450606088015193506080880151925061401360a08901613fad565b915061402160c08901613e38565b905092959891949750929550565b60208082526022908201527f5641495f4d494e545f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b5f60208284031215614081575f80fd5b61150482613fad565b60208082526022908201527f5641495f4255524e5f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b6020808252602e908201527f5641495f43555252454e545f494e5445524553545f414d4f554e545f43414c4360408201526d155310551253d397d1905253115160921b606082015260800190565b60208082526024908201527f5641495f504153545f494e5445524553545f43414c43554c4154494f4e5f46416040820152631253115160e21b606082015260800190565b60208082526021908201527f5641495f52455041595f524154455f43414c43554c4154494f4e5f4641494c456040820152601160fa1b606082015260800190565b60208082526029908201527f5641495f544f54414c5f52455041595f414d4f554e545f43414c43554c41544960408201526813d397d1905253115160ba1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a5957610a596141e8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f9061374b9083018461420f565b5f8261427a57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52600160045260245ffd5b80820180821115610a5957610a596141e8565b602081525f611504602083018461420f565b8082028115828204841417610a5957610a596141e856fea26469706673582212206eb9e4fce6049c92043fdf95235dced95a1f7fd5ce40415c966d53a8db9d82ec64736f6c63430008190033", "devdoc": { "author": "Venus", "events": { @@ -1461,7 +1461,7 @@ "storageLayout": { "storage": [ { - "astId": 32532, + "astId": 42518, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "admin", "offset": 0, @@ -1469,7 +1469,7 @@ "type": "t_address" }, { - "astId": 32535, + "astId": 42521, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "pendingAdmin", "offset": 0, @@ -1477,7 +1477,7 @@ "type": "t_address" }, { - "astId": 32538, + "astId": 42524, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "vaiControllerImplementation", "offset": 0, @@ -1485,7 +1485,7 @@ "type": "t_address" }, { - "astId": 32541, + "astId": 42527, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "pendingVAIControllerImplementation", "offset": 0, @@ -1493,23 +1493,23 @@ "type": "t_address" }, { - "astId": 32547, + "astId": 42533, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "comptroller", "offset": 0, "slot": "4", - "type": "t_contract(ComptrollerInterface)4740" + "type": "t_contract(ComptrollerInterface)9117" }, { - "astId": 32558, + "astId": 42544, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "venusVAIState", "offset": 0, "slot": "5", - "type": "t_struct(VenusVAIState)32554_storage" + "type": "t_struct(VenusVAIState)42540_storage" }, { - "astId": 32561, + "astId": 42547, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "isVenusVAIInitialized", "offset": 0, @@ -1517,7 +1517,7 @@ "type": "t_bool" }, { - "astId": 32566, + "astId": 42552, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "venusVAIMinterIndex", "offset": 0, @@ -1525,7 +1525,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 32572, + "astId": 42558, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "treasuryGuardian", "offset": 0, @@ -1533,7 +1533,7 @@ "type": "t_address" }, { - "astId": 32575, + "astId": 42561, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "treasuryAddress", "offset": 0, @@ -1541,7 +1541,7 @@ "type": "t_address" }, { - "astId": 32578, + "astId": 42564, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "treasuryPercent", "offset": 0, @@ -1549,7 +1549,7 @@ "type": "t_uint256" }, { - "astId": 32581, + "astId": 42567, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "_notEntered", "offset": 0, @@ -1557,7 +1557,7 @@ "type": "t_bool" }, { - "astId": 32584, + "astId": 42570, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "baseRateMantissa", "offset": 0, @@ -1565,7 +1565,7 @@ "type": "t_uint256" }, { - "astId": 32587, + "astId": 42573, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "floatRateMantissa", "offset": 0, @@ -1573,7 +1573,7 @@ "type": "t_uint256" }, { - "astId": 32590, + "astId": 42576, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "receiver", "offset": 0, @@ -1581,7 +1581,7 @@ "type": "t_address" }, { - "astId": 32593, + "astId": 42579, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "vaiMintIndex", "offset": 0, @@ -1589,7 +1589,7 @@ "type": "t_uint256" }, { - "astId": 32596, + "astId": 42582, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "accrualBlockNumber", "offset": 0, @@ -1597,7 +1597,7 @@ "type": "t_uint256" }, { - "astId": 32601, + "astId": 42587, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "vaiMinterInterestIndex", "offset": 0, @@ -1605,7 +1605,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 32606, + "astId": 42592, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "pastVAIInterest", "offset": 0, @@ -1613,7 +1613,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 32609, + "astId": 42595, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "mintCap", "offset": 0, @@ -1621,7 +1621,7 @@ "type": "t_uint256" }, { - "astId": 32612, + "astId": 42598, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "accessControl", "offset": 0, @@ -1629,7 +1629,7 @@ "type": "t_address" }, { - "astId": 32618, + "astId": 42604, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "prime", "offset": 0, @@ -1637,7 +1637,7 @@ "type": "t_address" }, { - "astId": 32621, + "astId": 42607, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "mintEnabledOnlyForPrimeHolder", "offset": 20, @@ -1645,7 +1645,7 @@ "type": "t_bool" }, { - "astId": 32627, + "astId": 42613, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "vai", "offset": 0, @@ -1664,7 +1664,7 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(ComptrollerInterface)4740": { + "t_contract(ComptrollerInterface)9117": { "encoding": "inplace", "label": "contract ComptrollerInterface", "numberOfBytes": "20" @@ -1676,12 +1676,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_struct(VenusVAIState)32554_storage": { + "t_struct(VenusVAIState)42540_storage": { "encoding": "inplace", "label": "struct VAIControllerStorageG1.VenusVAIState", "members": [ { - "astId": 32550, + "astId": 42536, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "index", "offset": 0, @@ -1689,7 +1689,7 @@ "type": "t_uint224" }, { - "astId": 32553, + "astId": 42539, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "block", "offset": 28, diff --git a/deployments/bscmainnet/solcInputs/cbc4287e135101fe4c78448d0f5f2ecc.json b/deployments/bscmainnet/solcInputs/cbc4287e135101fe4c78448d0f5f2ecc.json new file mode 100644 index 000000000..d590d2c4f --- /dev/null +++ b/deployments/bscmainnet/solcInputs/cbc4287e135101fe4c78448d0f5f2ecc.json @@ -0,0 +1,469 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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 amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\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(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, 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(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\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(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease 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 safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\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(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\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(IERC20Upgradeable 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\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCastUpgradeable {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1967.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/IERC1967.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967Upgrade is IERC1967 {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n ITransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}\n * does not implement this interface directly, and some of its functions are implemented by an internal dispatch\n * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not\n * include them in the ABI so this interface must be used to interact with it.\n */\ninterface ITransparentUpgradeableProxy is IERC1967 {\n function admin() external view returns (address);\n\n function implementation() external view returns (address);\n\n function changeAdmin(address) external;\n\n function upgradeTo(address) external;\n\n function upgradeToAndCall(address, bytes memory) external payable;\n}\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n *\n * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not\n * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch\n * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to\n * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the\n * implementation.\n *\n * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler\n * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function\n * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could\n * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) {\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n *\n * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the\n * implementation provides a function with the same selector.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior\n */\n function _fallback() internal virtual override {\n if (msg.sender == _getAdmin()) {\n bytes memory ret;\n bytes4 selector = msg.sig;\n if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) {\n ret = _dispatchUpgradeTo();\n } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) {\n ret = _dispatchUpgradeToAndCall();\n } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) {\n ret = _dispatchChangeAdmin();\n } else if (selector == ITransparentUpgradeableProxy.admin.selector) {\n ret = _dispatchAdmin();\n } else if (selector == ITransparentUpgradeableProxy.implementation.selector) {\n ret = _dispatchImplementation();\n } else {\n revert(\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n }\n assembly {\n return(add(ret, 0x20), mload(ret))\n }\n } else {\n super._fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function _dispatchAdmin() private returns (bytes memory) {\n _requireZeroValue();\n\n address admin = _getAdmin();\n return abi.encode(admin);\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function _dispatchImplementation() private returns (bytes memory) {\n _requireZeroValue();\n\n address implementation = _implementation();\n return abi.encode(implementation);\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _dispatchChangeAdmin() private returns (bytes memory) {\n _requireZeroValue();\n\n address newAdmin = abi.decode(msg.data[4:], (address));\n _changeAdmin(newAdmin);\n\n return \"\";\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n */\n function _dispatchUpgradeTo() private returns (bytes memory) {\n _requireZeroValue();\n\n address newImplementation = abi.decode(msg.data[4:], (address));\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n\n return \"\";\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n */\n function _dispatchUpgradeToAndCall() private returns (bytes memory) {\n (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));\n _upgradeToAndCall(newImplementation, data, true);\n\n return \"\";\n }\n\n /**\n * @dev Returns the current admin.\n *\n * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to\n * emulate some proxy functions being non-payable while still allowing value to pass through.\n */\n function _requireZeroValue() private {\n require(msg.value == 0);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev 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 amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\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.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\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\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 internal _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/DeviationBoundedOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { VBep20Interface } from \"./interfaces/VBep20Interface.sol\";\nimport { ResilientOracleInterface } from \"./interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"./interfaces/IDeviationBoundedOracle.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { Transient } from \"./lib/Transient.sol\";\n\n/**\n * @title DeviationBoundedOracle\n * @author Venus\n * @notice The DeviationBoundedOracle provides manipulation-resistant pricing for lending operations.\n *\n * It maintains a per-market rolling min/max price window. When the current spot price deviates\n * significantly from the window bounds, protection mode activates automatically and conservative\n * pricing kicks in:\n * - Collateral is valued at min(spot, windowMin) — caps collateral value at recent window low\n * - Debt is valued at max(spot, windowMax) — floors debt value at recent window high\n *\n * This protects against instantaneous or short-duration price manipulation attacks on low-liquidity\n * collateral tokens. Sustained attacks beyond the window period are expected to be handled by\n * off-chain monitoring systems.\n *\n * The oracle exposes both view and non-view price functions. The non-view variants update the\n * price window and trigger protection. The view variants read stored state only. A transient\n * price cache avoids redundant ResilientOracle calls within the same transaction when\n * updateProtectionState is called before the view price reads.\n */\ncontract DeviationBoundedOracle is AccessControlledV8, IDeviationBoundedOracle {\n /// @notice Minimum allowed threshold value (5%) to account for keeper deadband\n uint256 public constant MIN_THRESHOLD = 5e16;\n\n /// @notice Maximum allowed threshold value (50%)\n uint256 public constant MAX_THRESHOLD = 50e16;\n\n /// @notice Keeper deadband threshold (5%) — min/max corrections below this are suppressed\n uint256 public constant KEEPER_DEADBAND = 5e16;\n\n /// @notice Resilient Oracle used to fetch spot prices\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ResilientOracleInterface public immutable RESILIENT_ORACLE;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Transient storage slot for caching final collateral prices within a transaction\n /// @dev custom:storage-location erc7201:venus-protocol/oracle/DeviationBoundedOracle/collateralCache\n /// keccak256(abi.encode(uint256(keccak256(\"venus-protocol/oracle/DeviationBoundedOracle/collateralCache\")) - 1))\n /// & ~bytes32(uint256(0xff))\n bytes32 public constant COLLATERAL_PRICE_CACHE_SLOT =\n 0x7bd9fcecef8429101f34baefb335883a97edd91e0d8fdc455d73ab727abf7000;\n\n /// @notice Transient storage slot for caching final debt prices within a transaction\n /// @dev custom:storage-location erc7201:venus-protocol/oracle/DeviationBoundedOracle/debtCache\n /// keccak256(abi.encode(uint256(keccak256(\"venus-protocol/oracle/DeviationBoundedOracle/debtCache\")) - 1))\n /// & ~bytes32(uint256(0xff))\n bytes32 public constant DEBT_PRICE_CACHE_SLOT = 0x84d6ca795decc666d3d1d524cbbadd8a1e0e0279db766fe7a1b41b1eb8970600;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Per-asset protection state\n mapping(address => MarketProtectionState) public assetProtectionConfig;\n\n /// @notice Append-only array of all assets ever initialized, used for enumeration\n address[] public allAssets;\n\n /// @notice Storage gap for upgrades\n uint256[48] private __gap;\n\n /**\n * @notice Constructor for the implementation contract. Sets immutable variables.\n * @param _resilientOracle Address of the ResilientOracle contract\n * @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n * @param vaiAddress The address of the VAI token, or address(0) if VAI is not deployed on the chain.\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(ResilientOracleInterface _resilientOracle, address nativeMarketAddress, address vaiAddress) {\n ensureNonzeroAddress(address(_resilientOracle));\n ensureNonzeroAddress(nativeMarketAddress);\n RESILIENT_ORACLE = _resilientOracle;\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n }\n\n // ----- Non-view price functions (update window + trigger protection) -----\n\n /**\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\n * @dev Fetches spot from ResilientOracle, updates the price window, checks trigger,\n * and returns the conservative (lower) price when protection is active.\n * Used by keepers or direct callers who want atomic update + read.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice) {\n (collateralPrice, ) = _updateAndGetBoundedPrices(vToken);\n }\n\n /**\n * @notice Gets the bounded debt price for a given vToken, updating protection state\n * @dev Fetches spot from ResilientOracle, updates the price window, checks trigger,\n * and returns the conservative (higher) price when protection is active.\n * Used by keepers or direct callers who want atomic update + read.\n * @param vToken vToken address\n * @return debtPrice The bounded debt price\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice) {\n (, debtPrice) = _updateAndGetBoundedPrices(vToken);\n }\n\n /**\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\n * @dev Fetches spot from ResilientOracle, updates the price window, checks trigger,\n * and returns both conservative prices in a single call.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @return debtPrice The bounded debt price\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice) {\n return _updateAndGetBoundedPrices(vToken);\n }\n\n /**\n * @notice Fetches the spot price, updates the protection window, and caches the resolved\n * collateral and debt prices in transient storage for the duration of the transaction.\n * @dev Call this once per vToken at the start of a transaction (e.g. from PolicyFacet before\n * liquidity calculations). Subsequent calls to getBoundedCollateralPriceView /\n * getBoundedDebtPriceView within the same transaction will read from the transient cache\n * instead of querying ResilientOracle again, keeping those functions as `view` and\n * avoiding redundant oracle calls.\n * The transient cache is only populated when the asset's `cachingEnabled` flag is `true`.\n * When caching is disabled, view price reads fall through to live recomputation.\n * Permissionless: anyone can call this, both for gas optimisation and to ensure every\n * caller in the same transaction reads the correct, up-to-date bounded price.\n * @param vToken vToken address\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function updateProtectionState(address vToken) external {\n _updateAndGetBoundedPrices(vToken);\n }\n\n // ----- View price functions (read stored/cached state only) -----\n\n /**\n * @notice Gets the bounded collateral price for a given vToken (view variant)\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`\n * (populated by a prior updateProtectionState call in the same transaction). Falls back\n * to ResilientOracle on cache miss or when caching is disabled.\n * Returns min(spot, windowMin) when protection is active, spot otherwise.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n */\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 collateralPrice) {\n (collateralPrice, ) = _computeBoundedPrices(vToken);\n }\n\n /**\n * @notice Gets the bounded debt price for a given vToken (view variant)\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`\n * (populated by a prior updateProtectionState call in the same transaction). Falls back\n * to ResilientOracle on cache miss or when caching is disabled.\n * Returns max(spot, windowMax) when protection is active, spot otherwise.\n * @param vToken vToken address\n * @return debtPrice The bounded debt price\n */\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 debtPrice) {\n (, debtPrice) = _computeBoundedPrices(vToken);\n }\n\n /**\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\n * falls back to ResilientOracle on cache miss or when caching is disabled.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @return debtPrice The bounded debt price\n */\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice) {\n return _computeBoundedPrices(vToken);\n }\n\n // ----- Keeper functions -----\n\n /**\n * @notice Updates the minimum price in the rolling window for a given asset\n * @dev Called by the keeper to push corrected min values from the off-chain sliding window.\n * Constraint: newMin must be at or below the current spot price.\n * @param asset The underlying asset address\n * @param newMin The new minimum price\n * @custom:access Only authorized keeper addresses\n * @custom:event MinPriceUpdated\n */\n function updateMinPrice(address asset, uint128 newMin) external {\n _checkAccessAllowed(\"updateMinPrice(address,uint128)\");\n _validateAndUpdateBound(asset, newMin, PriceBoundType.MIN);\n }\n\n /**\n * @notice Updates the maximum price in the rolling window for a given asset\n * @dev Called by the keeper to push corrected max values from the off-chain sliding window.\n * Constraint: newMax must be at or above the current spot price.\n * @param asset The underlying asset address\n * @param newMax The new maximum price\n * @custom:access Only authorized keeper addresses\n * @custom:event MaxPriceUpdated\n */\n function updateMaxPrice(address asset, uint128 newMax) external {\n _checkAccessAllowed(\"updateMaxPrice(address,uint128)\");\n _validateAndUpdateBound(asset, newMax, PriceBoundType.MAX);\n }\n\n /**\n * @notice Exits protection mode for a given asset\n * @dev Called by the keeper/monitor after confirming price has normalised.\n * Enforces two conditions on-chain:\n * 1. Cooldown period has elapsed since the last trigger\n * 2. Price range has converged below the exit threshold\n * @param asset The underlying asset address\n * @custom:access Only authorized monitor/keeper addresses\n * @custom:error ProtectedPriceInactive if protection is not currently active\n * @custom:error CooldownNotElapsed if cooldown period has not elapsed\n * @custom:error PriceRangeNotConverged if window range is still above exit threshold\n * @custom:event ProtectionModeExited\n */\n function exitProtectionMode(address asset) external {\n _checkAccessAllowed(\"exitProtectionMode(address)\");\n _exitProtectionMode(asset);\n }\n\n /**\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\n * Empty `actions` is a no-op success.\n * @param actions The list of keeper actions to apply\n * @custom:access Only authorized keeper addresses\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\n */\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external {\n _checkAccessAllowed(\"syncPriceBoundsAndProtections((address,uint8,uint256)[])\");\n uint256 len = actions.length;\n for (uint256 i; i < len; ++i) {\n KeeperActionItem calldata item = actions[i];\n if (item.action == KeeperAction.SetMinPrice) {\n _validateAndUpdateBound(item.asset, _safeToUint128(item.value), PriceBoundType.MIN);\n } else if (item.action == KeeperAction.SetMaxPrice) {\n _validateAndUpdateBound(item.asset, _safeToUint128(item.value), PriceBoundType.MAX);\n } else if (item.action == KeeperAction.ExitProtectionMode) {\n _exitProtectionMode(item.asset);\n } else {\n revert InvalidKeeperAction(uint8(item.action));\n }\n }\n }\n\n // ----- Admin functions (governance-gated) -----\n\n /**\n * @notice Initializes protection for a new asset\n * @param tokenConfig_ Token config input for the asset\n * @custom:access Only Governance\n * @custom:event ProtectionInitialized\n * @custom:event BoundedPricingWhitelistUpdated\n */\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external {\n _checkAccessAllowed(\"setTokenConfig((address,uint64,uint256,uint256,bool,bool))\");\n _setTokenConfig(\n tokenConfig_.asset,\n tokenConfig_.cooldownPeriod,\n tokenConfig_.triggerThreshold,\n tokenConfig_.resetThreshold,\n tokenConfig_.enableBoundedPricing,\n tokenConfig_.enableCaching\n );\n }\n\n /**\n * @notice Batch-initializes protection for multiple assets in a single transaction\n * @param tokenConfigs_ Array of token config inputs, one per asset\n * @custom:access Only Governance\n * @custom:error InvalidArrayLength if the input array is empty\n * @custom:event ProtectionInitialized for each asset\n * @custom:event BoundedPricingWhitelistUpdated for each asset\n */\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external {\n _checkAccessAllowed(\"setTokenConfigs((address,uint64,uint256,uint256,bool,bool)[])\");\n uint256 len = tokenConfigs_.length;\n if (len == 0) revert InvalidArrayLength();\n\n for (uint256 i; i < len; ++i) {\n TokenConfigInput calldata tokenConfig = tokenConfigs_[i];\n _setTokenConfig(\n tokenConfig.asset,\n tokenConfig.cooldownPeriod,\n tokenConfig.triggerThreshold,\n tokenConfig.resetThreshold,\n tokenConfig.enableBoundedPricing,\n tokenConfig.enableCaching\n );\n }\n }\n\n /**\n * @notice Sets the cooldown period for an asset\n * @param asset The underlying asset address\n * @param newCooldown The new cooldown period in seconds\n * @custom:access Only Governance\n * @custom:event CooldownPeriodSet\n */\n function setCooldownPeriod(address asset, uint64 newCooldown) external {\n _checkAccessAllowed(\"setCooldownPeriod(address,uint64)\");\n ensureNonzeroAddress(asset);\n ensureNonzeroValue(newCooldown);\n\n MarketProtectionState storage state = _ensureInitialized(asset);\n emit CooldownPeriodSet(asset, state.cooldownPeriod, newCooldown);\n state.cooldownPeriod = newCooldown;\n }\n\n /**\n * @notice Sets the trigger and reset thresholds for an asset\n * @param asset The underlying asset address\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\n * @custom:access Only Governance\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\n * @custom:event TriggerThresholdSet if the trigger threshold changed\n * @custom:event ResetThresholdSet if the reset threshold changed\n */\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external {\n _checkAccessAllowed(\"setThresholds(address,uint256,uint256)\");\n ensureNonzeroAddress(asset);\n ensureNonzeroValue(newTriggerThreshold);\n ensureNonzeroValue(newResetThreshold);\n if (newTriggerThreshold < MIN_THRESHOLD) revert ThresholdBelowMinimum(newTriggerThreshold, MIN_THRESHOLD);\n if (newTriggerThreshold > MAX_THRESHOLD) revert ThresholdAboveMaximum(newTriggerThreshold, MAX_THRESHOLD);\n if (newResetThreshold >= newTriggerThreshold) revert InvalidResetThreshold(newResetThreshold);\n MarketProtectionState storage state = _ensureInitialized(asset);\n\n if (newTriggerThreshold != state.triggerThreshold) {\n emit TriggerThresholdSet(asset, state.triggerThreshold, newTriggerThreshold);\n state.triggerThreshold = uint128(newTriggerThreshold);\n }\n if (newResetThreshold != state.resetThreshold) {\n emit ResetThresholdSet(asset, state.resetThreshold, newResetThreshold);\n state.resetThreshold = uint128(newResetThreshold);\n }\n }\n\n /**\n * @notice Sets whether an asset is enabled for bounded pricing\n * @param asset The underlying asset address\n * @param enabled Whether bounded pricing should be enabled for the asset\n * @custom:access Only Governance\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\n * @custom:event BoundedPricingWhitelistUpdated\n */\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external {\n _checkAccessAllowed(\"setAssetBoundedPricingEnabled(address,bool)\");\n ensureNonzeroAddress(asset);\n\n MarketProtectionState storage state = _ensureInitialized(asset);\n\n if (!enabled && state.currentlyUsingProtectedPrice) {\n revert ProtectedPriceActive(asset);\n }\n\n if (state.isBoundedPricingEnabled == enabled) return;\n\n // reset the window if re-enabling\n if (enabled) {\n uint128 spotU128 = _safeToUint128(_fetchSpotPrice(asset));\n _setMinPrice(state, asset, spotU128);\n _setMaxPrice(state, asset, spotU128);\n }\n\n state.isBoundedPricingEnabled = enabled;\n emit BoundedPricingWhitelistUpdated(asset, enabled);\n }\n\n /**\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\n * live spot instead of reading or writing the transient slots. The initial value is\n * set via the `enableCaching` argument of `setTokenConfig`.\n * @param asset The underlying asset address\n * @param enabled Whether transient caching is enabled for this asset\n * @custom:access Only Governance\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:event CachingEnabledUpdated\n */\n function setCachingEnabled(address asset, bool enabled) external {\n _checkAccessAllowed(\"setCachingEnabled(address,bool)\");\n MarketProtectionState storage state = _ensureInitialized(asset);\n emit CachingEnabledUpdated(asset, state.cachingEnabled, enabled);\n state.cachingEnabled = enabled;\n }\n\n // ----- View helpers -----\n\n /**\n * @notice Returns all asset addresses that have ever been initialized\n * @return Array of all initialized asset addresses\n */\n function getInitializedAssets() external view returns (address[] memory) {\n return allAssets;\n }\n\n /**\n * @notice Checks if an asset is whitelisted for bounded pricing\n * @param asset The underlying asset address\n * @return True if the asset is whitelisted\n */\n function isBoundedPricingEnabled(address asset) external view returns (bool) {\n return assetProtectionConfig[asset].isBoundedPricingEnabled;\n }\n\n /**\n * @notice Checks if the asset is currently using the protected (bounded) price\n * @param asset The underlying asset address\n * @return True if the asset is currently using the protected price instead of spot\n */\n function currentlyUsingProtectedPrice(address asset) external view returns (bool) {\n return assetProtectionConfig[asset].currentlyUsingProtectedPrice;\n }\n\n /**\n * @notice Returns all currently whitelisted asset addresses\n * @dev Iterates the append-only allAssets array and filters by isBoundedPricingEnabled.\n * Gas-free for off-chain callers.\n * @return result Array of whitelisted asset addresses\n */\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory) {\n uint256 len = allAssets.length;\n address[] memory temp = new address[](len);\n uint256 count;\n for (uint256 i; i < len; ++i) {\n if (assetProtectionConfig[allAssets[i]].isBoundedPricingEnabled) {\n temp[count++] = allAssets[i];\n }\n }\n address[] memory result = new address[](count);\n for (uint256 i; i < count; ++i) {\n result[i] = temp[i];\n }\n return result;\n }\n\n /**\n * @notice Checks if protection can be exited for an asset\n * @dev Returns true when both conditions are met:\n * 1. Cooldown period has elapsed since last trigger\n * 2. Price range has converged below exit threshold\n * @param asset The underlying asset address\n * @return True if protection can be disabled\n */\n function canExitProtection(address asset) external view returns (bool) {\n MarketProtectionState storage state = assetProtectionConfig[asset];\n return\n state.currentlyUsingProtectedPrice &&\n block.timestamp >= uint256(state.lastProtectionTriggeredAt) + uint256(state.cooldownPeriod) &&\n _computePriceBoundRatio(state.minPrice, state.maxPrice) < state.resetThreshold;\n }\n\n /**\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the deadband\n * from the keeper's proposed window values\n * @dev Allows the keeper to identify stale windows in a single call, avoiding N individual reads.\n * Drift formula: |onChain - proposed| / onChain (scaled by EXP_SCALE)\n * @param assets Array of asset addresses to check\n * @param proposedMins Keeper's off-chain window minimum prices\n * @param proposedMaxs Keeper's off-chain window maximum prices\n * @return needsMinUpdate Whether minPrice drift exceeds deadband for each asset\n * @return needsMaxUpdate Whether maxPrice drift exceeds deadband for each asset\n * @custom:error InvalidArrayLength if the input array lengths do not match\n */\n function checkAndGetWindowDrift(\n address[] calldata assets,\n uint128[] calldata proposedMins,\n uint128[] calldata proposedMaxs\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate) {\n uint256 len = assets.length;\n if (len != proposedMins.length || len != proposedMaxs.length) revert InvalidArrayLength();\n\n needsMinUpdate = new bool[](len);\n needsMaxUpdate = new bool[](len);\n\n for (uint256 i; i < len; ++i) {\n MarketProtectionState storage state = assetProtectionConfig[assets[i]];\n needsMinUpdate[i] = _exceedsCorrectionDeadband(state.minPrice, proposedMins[i]);\n needsMaxUpdate[i] = _exceedsCorrectionDeadband(state.maxPrice, proposedMaxs[i]);\n }\n }\n\n // ----- Internal functions -----\n\n /**\n * @notice Initializes protection parameters and price window for a single asset\n * @dev Fetches the current spot price from ResilientOracle to seed the initial min/max window,\n * confirming the oracle is live for this asset before it is listed. Both bounds start at\n * spot so the window expands naturally as prices move. Can only be called once per asset.\n * @param asset The underlying asset address\n * @param cooldownPeriod Minimum time protection stays active after last trigger\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\n * @param enableCaching Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\n * @custom:error VAINotAllowed if asset is the VAI token\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n */\n function _setTokenConfig(\n address asset,\n uint64 cooldownPeriod,\n uint256 triggerThreshold,\n uint256 resetThreshold,\n bool enableBoundedPricing,\n bool enableCaching\n ) internal {\n ensureNonzeroAddress(asset);\n ensureNonzeroValue(cooldownPeriod);\n ensureNonzeroValue(triggerThreshold);\n ensureNonzeroValue(resetThreshold);\n if (assetProtectionConfig[asset].asset != address(0)) revert MarketAlreadyInitialized(asset);\n if (triggerThreshold < MIN_THRESHOLD) revert ThresholdBelowMinimum(triggerThreshold, MIN_THRESHOLD);\n if (triggerThreshold > MAX_THRESHOLD) revert ThresholdAboveMaximum(triggerThreshold, MAX_THRESHOLD);\n if (resetThreshold >= triggerThreshold) revert InvalidResetThreshold(resetThreshold);\n if (asset == vai) revert VAINotAllowed();\n\n uint128 spotU128 = _safeToUint128(_fetchSpotPrice(asset));\n\n assetProtectionConfig[asset] = MarketProtectionState({\n minPrice: spotU128,\n maxPrice: spotU128,\n currentlyUsingProtectedPrice: false,\n isBoundedPricingEnabled: enableBoundedPricing,\n lastProtectionTriggeredAt: 0,\n cooldownPeriod: cooldownPeriod,\n asset: asset,\n triggerThreshold: uint128(triggerThreshold),\n resetThreshold: uint128(resetThreshold),\n cachingEnabled: enableCaching\n });\n\n allAssets.push(asset);\n\n emit ProtectionInitialized(asset, spotU128, spotU128, cooldownPeriod, triggerThreshold);\n emit BoundedPricingWhitelistUpdated(asset, enableBoundedPricing);\n }\n\n /**\n * @notice Validates and applies a keeper-provided min or max price update\n * @param asset The underlying asset address\n * @param newPrice The new price value to set\n * @param boundType Whether this is a MIN or MAX bound update\n * @custom:error ZeroPriceNotAllowed if newPrice is zero\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error InvalidMinPrice if boundType is MIN and newPrice exceeds the current spot or is strictly above maxPrice\n * @custom:error InvalidMaxPrice if boundType is MAX and newPrice is below the current spot or is strictly below minPrice\n */\n function _validateAndUpdateBound(address asset, uint128 newPrice, PriceBoundType boundType) internal {\n ensureNonzeroAddress(asset);\n if (newPrice == 0) revert ZeroPriceNotAllowed();\n MarketProtectionState storage state = _ensureInitialized(asset);\n\n uint256 currentSpot = _fetchSpotPrice(asset);\n if (boundType == PriceBoundType.MIN) {\n if (newPrice > state.maxPrice || uint256(newPrice) > currentSpot)\n revert InvalidMinPrice(asset, newPrice, currentSpot);\n _setMinPrice(state, asset, newPrice);\n } else if (boundType == PriceBoundType.MAX) {\n if (newPrice < state.minPrice || uint256(newPrice) < currentSpot)\n revert InvalidMaxPrice(asset, newPrice, currentSpot);\n _setMaxPrice(state, asset, newPrice);\n }\n }\n\n /**\n * @notice Clears protection for an asset once cooldown has elapsed and the window has converged\n * @dev Shared body of `exitProtectionMode` and the ExitProtectionMode branch of `syncPriceBoundsAndProtections`.\n * Callers are responsible for ACM gating before invoking this helper.\n * @param asset The underlying asset address\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error ProtectedPriceInactive if protection is not currently active\n * @custom:error CooldownNotElapsed if cooldown period has not elapsed\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\n */\n function _exitProtectionMode(address asset) internal {\n ensureNonzeroAddress(asset);\n MarketProtectionState storage state = _ensureInitialized(asset);\n\n if (!state.currentlyUsingProtectedPrice) revert ProtectedPriceInactive(asset);\n\n if (block.timestamp < uint256(state.lastProtectionTriggeredAt) + uint256(state.cooldownPeriod)) {\n revert CooldownNotElapsed(asset, state.lastProtectionTriggeredAt, state.cooldownPeriod);\n }\n\n uint256 rangeRatio = _computePriceBoundRatio(state.minPrice, state.maxPrice);\n if (rangeRatio >= state.resetThreshold) {\n revert PriceRangeNotConverged(asset, rangeRatio, state.resetThreshold);\n }\n\n state.currentlyUsingProtectedPrice = false;\n state.lastProtectionTriggeredAt = 0;\n emit ProtectionModeExited(asset);\n }\n\n /**\n * @notice Shared non-view logic for all bounded price functions.\n * Fetches spot, updates window, triggers protection if needed, and returns both bounded prices.\n * @param vToken vToken address\n * @return minPrice The bounded lower (collateral) price\n * @return maxPrice The bounded upper (debt) price\n */\n function _updateAndGetBoundedPrices(address vToken) internal returns (uint256 minPrice, uint256 maxPrice) {\n address asset = _getUnderlyingAsset(vToken);\n\n // Early return if both prices were cached by a prior updateProtectionState call in this tx\n (minPrice, maxPrice) = _getCachedPrices(asset);\n if (minPrice != 0 && maxPrice != 0) return (minPrice, maxPrice);\n\n // return early if failure from resilient oracle to prevent cold SLOAD\n uint256 spot = _fetchSpotPrice(asset);\n MarketProtectionState storage state = assetProtectionConfig[asset];\n if (!state.isBoundedPricingEnabled) {\n _setCachedPrices(asset, spot, spot);\n return (spot, spot);\n }\n (uint128 updatedMin, uint128 updatedMax, bool windowExpanded) = _expandPriceWindow(state, spot, asset);\n bool protectionActive = _checkAndTriggerProtection(state, spot, asset, windowExpanded);\n (minPrice, maxPrice) = _resolveBoundedPrices(protectionActive, spot, uint256(updatedMin), uint256(updatedMax));\n _setCachedPrices(asset, minPrice, maxPrice);\n }\n\n /**\n * @dev Expands the price window toward extremes if the spot price is a new min or max\n * @param state The market protection state\n * @param spot The current spot price\n * @param asset The underlying asset address (for event emission)\n */\n function _expandPriceWindow(\n MarketProtectionState storage state,\n uint256 spot,\n address asset\n ) internal returns (uint128, uint128, bool) {\n uint128 spotU128 = _safeToUint128(spot);\n uint128 currentMin = state.minPrice;\n uint128 currentMax = state.maxPrice;\n bool windowExpanded;\n if (spotU128 < currentMin) {\n _setMinPrice(state, asset, spotU128);\n currentMin = spotU128;\n windowExpanded = true;\n }\n if (spotU128 > currentMax) {\n _setMaxPrice(state, asset, spotU128);\n currentMax = spotU128;\n windowExpanded = true;\n }\n return (currentMin, currentMax, windowExpanded);\n }\n\n /**\n * @dev Checks if the spot price has deviated beyond the threshold and triggers protection.\n * `lastProtectionTriggeredAt` is reset only on the first trigger or when the price has made a\n * genuine new extreme this update (windowExpanded == true). Recovery within the existing window\n * keeps the cooldown ticking so `exitProtectionMode` remains reachable.\n * @param state The market protection state\n * @param spot The current spot price\n * @param asset The underlying asset address (for event emission)\n * @param windowExpanded True if `_expandPriceWindow` recorded a new low or new high this call\n */\n function _checkAndTriggerProtection(\n MarketProtectionState storage state,\n uint256 spot,\n address asset,\n bool windowExpanded\n ) internal returns (bool triggered) {\n if (_exceedsDeviationThreshold(spot, state.minPrice, state.maxPrice, state.triggerThreshold)) {\n bool enteringProtection = !state.currentlyUsingProtectedPrice;\n if (enteringProtection || windowExpanded) {\n state.lastProtectionTriggeredAt = uint64(block.timestamp);\n }\n if (enteringProtection) {\n state.currentlyUsingProtectedPrice = true;\n }\n emit ProtectionTriggered(asset, spot, state.minPrice, state.maxPrice);\n return true;\n }\n if (state.currentlyUsingProtectedPrice) return true;\n }\n\n /**\n * @notice Resolves the final bounded collateral and debt prices given a spot, window bounds, and protection flag.\n * @dev When protection is active: collateral = min(spot, windowMin), debt = max(spot, windowMax).\n * When protection is inactive: both return spot.\n * @param protectionActive Whether the market protection window is currently active\n * @param spot The current spot price\n * @param windowMin The lower bound of the price window\n * @param windowMax The upper bound of the price window\n * @return minPrice The resolved lower-bound (collateral) price\n * @return maxPrice The resolved upper-bound (debt) price\n */\n function _resolveBoundedPrices(\n bool protectionActive,\n uint256 spot,\n uint256 windowMin,\n uint256 windowMax\n ) internal pure returns (uint256, uint256) {\n if (!protectionActive) return (spot, spot);\n return (spot < windowMin ? spot : windowMin, spot > windowMax ? spot : windowMax);\n }\n\n /**\n * @notice Shared view logic for all bounded price view functions.\n * Checks transient cache first for an early return; on miss, fetches from oracle\n * and computes both prices without state mutations.\n * @param vToken vToken address\n * @return minPrice The bounded lower (collateral) price\n * @return maxPrice The bounded upper (debt) price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\n */\n function _computeBoundedPrices(address vToken) internal view returns (uint256 minPrice, uint256 maxPrice) {\n address asset = _getUnderlyingAsset(vToken);\n\n // Early return if both prices were cached by a prior updateProtectionState call in this tx\n (minPrice, maxPrice) = _getCachedPrices(asset);\n if (minPrice != 0 && maxPrice != 0) return (minPrice, maxPrice);\n\n // Cache miss — fetch from oracle and compute without state mutations\n uint256 spot = _fetchSpotPrice(asset);\n MarketProtectionState storage state = assetProtectionConfig[asset];\n if (!state.isBoundedPricingEnabled) return (spot, spot);\n\n // Mirror _expandPriceWindow logic: compute what the window would be after expansion\n uint128 spotU128 = _safeToUint128(spot);\n uint128 windowMin128 = spot < uint256(state.minPrice) ? spotU128 : state.minPrice;\n uint128 windowMax128 = spot > uint256(state.maxPrice) ? spotU128 : state.maxPrice;\n\n bool shouldProtect = state.currentlyUsingProtectedPrice ||\n _exceedsDeviationThreshold(spot, windowMin128, windowMax128, state.triggerThreshold);\n\n (minPrice, maxPrice) = _resolveBoundedPrices(shouldProtect, spot, uint256(windowMin128), uint256(windowMax128));\n }\n\n /**\n * @dev Computes the relative spread between the price window bounds as a ratio scaled by EXP_SCALE.\n * Formula: \\((maxPrice - minPrice) / minPrice\\), scaled by `EXP_SCALE`.\n * Used to measure how much the window has converged -- compared against `resetThreshold`\n * to determine whether the price window is tight enough to exit protection mode.\n * @param minPrice The minimum price in the window\n * @param maxPrice The maximum price in the window\n * @return The scaled bound ratio \\(((max - min) * EXP_SCALE) / min\\)\n */\n function _computePriceBoundRatio(uint128 minPrice, uint128 maxPrice) internal pure returns (uint256) {\n uint256 range = uint256(maxPrice) - uint256(minPrice);\n return (range * EXP_SCALE) / uint256(minPrice);\n }\n\n /**\n * @notice Checks whether the spot price has moved beyond the threshold relative to the\n * opposite window bound — i.e. `spot > minPrice * (1 + threshold)` or\n * `spot < maxPrice * (1 - threshold)`.\n * @dev Pump detection: spot > minPrice * (1 + threshold)\n * Crash detection: spot < maxPrice * (1 - threshold)\n * @param spot The current spot price\n * @param minPrice The minimum price in the window\n * @param maxPrice The maximum price in the window\n * @param threshold The deviation threshold (mantissa)\n * @return True if deviation is triggered\n */\n function _exceedsDeviationThreshold(\n uint256 spot,\n uint128 minPrice,\n uint128 maxPrice,\n uint256 threshold\n ) internal pure returns (bool) {\n uint256 upperBound = (uint256(minPrice) * (EXP_SCALE + threshold)) / EXP_SCALE;\n uint256 lowerBound = (uint256(maxPrice) * (EXP_SCALE - threshold)) / EXP_SCALE;\n return (spot > upperBound || spot < lowerBound);\n }\n\n /**\n * @dev Returns true if the relative drift between onChain and proposed exceeds KEEPER_DEADBAND\n * @param currentPrice The current on-chain price\n * @param proposedPrice The keeper's proposed price\n * @return True if drift exceeds deadband\n */\n function _exceedsCorrectionDeadband(uint128 currentPrice, uint128 proposedPrice) internal pure returns (bool) {\n if (currentPrice == 0 || proposedPrice == 0) return false;\n uint256 diff = currentPrice > proposedPrice\n ? uint256(currentPrice - proposedPrice)\n : uint256(proposedPrice - currentPrice);\n return (diff * EXP_SCALE) / uint256(currentPrice) > KEEPER_DEADBAND;\n }\n\n /**\n * @dev Sets the minimum price in the window and emits MinPriceUpdated\n * @param state The market protection state\n * @param asset The underlying asset address (for event emission)\n * @param newMin The new minimum price\n */\n function _setMinPrice(MarketProtectionState storage state, address asset, uint128 newMin) internal {\n emit MinPriceUpdated(asset, state.minPrice, newMin);\n state.minPrice = newMin;\n }\n\n /**\n * @dev Sets the maximum price in the window and emits MaxPriceUpdated\n * @param state The market protection state\n * @param asset The underlying asset address (for event emission)\n * @param newMax The new maximum price\n */\n function _setMaxPrice(MarketProtectionState storage state, address asset, uint128 newMax) internal {\n emit MaxPriceUpdated(asset, state.maxPrice, newMax);\n state.maxPrice = newMax;\n }\n\n /**\n * @dev Writes both lower and upper bounded prices to transient storage. No-ops when the\n * asset's `cachingEnabled` flag is `false`, so callers that disable caching always\n * fall through to live recomputation on subsequent reads.\n * @param asset The underlying asset address\n * @param minPrice The resolved lower (collateral) price to cache\n * @param maxPrice The resolved upper (debt) price to cache\n */\n function _setCachedPrices(address asset, uint256 minPrice, uint256 maxPrice) internal {\n if (!assetProtectionConfig[asset].cachingEnabled) return;\n Transient.cachePrice(COLLATERAL_PRICE_CACHE_SLOT, asset, minPrice);\n Transient.cachePrice(DEBT_PRICE_CACHE_SLOT, asset, maxPrice);\n }\n\n /**\n * @dev Reads a cached final price from transient storage. Returns `(0, 0)` when the\n * asset's `cachingEnabled` flag is `false`, which callers already treat as a cache\n * miss and handle via live recomputation.\n * @param asset The underlying asset address\n * @return minPrice The cached minimum price, or 0 on cache miss\n * @return maxPrice The cached maximum price, or 0 on cache miss\n */\n function _getCachedPrices(address asset) internal view returns (uint256 minPrice, uint256 maxPrice) {\n if (!assetProtectionConfig[asset].cachingEnabled) return (0, 0);\n minPrice = Transient.readCachedPrice(COLLATERAL_PRICE_CACHE_SLOT, asset);\n maxPrice = Transient.readCachedPrice(DEBT_PRICE_CACHE_SLOT, asset);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view returns (address asset) {\n ensureNonzeroAddress(vToken);\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n\n /**\n * @dev Reverts if the market has not been initialized via setTokenConfig\n * @param asset The underlying asset address\n * @return state The market protection state storage pointer\n */\n function _ensureInitialized(address asset) internal view returns (MarketProtectionState storage state) {\n state = assetProtectionConfig[asset];\n if (state.asset == address(0)) revert MarketNotInitialized(asset);\n }\n\n /**\n * @notice Fetches the current spot price for an asset from the ResilientOracle\n * @param asset The underlying asset address\n * @return The current spot price\n */\n function _fetchSpotPrice(address asset) internal view returns (uint256) {\n return RESILIENT_ORACLE.getPrice(asset);\n }\n\n /**\n * @dev Safely casts a uint256 to uint128, reverting on overflow\n * @param value The value to cast\n * @return The value as uint128\n */\n function _safeToUint128(uint256 value) internal pure returns (uint128) {\n if (value > type(uint128).max) revert PriceExceedsUint128(value);\n return uint128(value);\n }\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IDeviationBoundedOracle {\n // --- Enums ---\n\n /// @notice Identifies whether a price bound is a minimum or maximum\n enum PriceBoundType {\n MIN,\n MAX\n }\n\n /// @notice Identifies which keeper action a single syncPriceBoundsAndProtections item performs\n enum KeeperAction {\n SetMinPrice,\n SetMaxPrice,\n ExitProtectionMode\n }\n\n // --- Structs ---\n\n /// @notice Per-asset protection state tracking the min/max price window\n struct MarketProtectionState {\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\n uint128 minPrice;\n /// @notice Highest price observed in the current window\n uint128 maxPrice;\n /// @notice Whether protected price is currently being used\n bool currentlyUsingProtectedPrice;\n /// @notice Whether this market is whitelisted for bounded pricing\n bool isBoundedPricingEnabled;\n /// @notice Timestamp of the last protection trigger — reset on every trigger\n uint64 lastProtectionTriggeredAt;\n /// @notice Minimum time protection stays active after last trigger\n uint64 cooldownPeriod;\n /// @notice The underlying asset address, used to verify initialization\n address asset;\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\n uint128 triggerThreshold;\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\n uint128 resetThreshold;\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\n bool cachingEnabled;\n }\n\n /// @notice One item in an syncPriceBoundsAndProtections payload\n /// @dev `value` is interpreted per-action: the new bound price for SetMinPrice / SetMaxPrice, ignored for ExitProtectionMode\n struct KeeperActionItem {\n address asset;\n KeeperAction action;\n uint256 value;\n }\n\n /// @notice One item in a setTokenConfigs payload\n struct TokenConfigInput {\n /// @notice The underlying asset address\n address asset;\n /// @notice Minimum time protection stays active after the last trigger (seconds)\n uint64 cooldownPeriod;\n /// @notice Entry deviation threshold (mantissa). Must be between 5% and 50%.\n uint256 triggerThreshold;\n /// @notice Exit deviation threshold (mantissa). Must be non-zero and below triggerThreshold.\n uint256 resetThreshold;\n /// @notice Whether to enable bounded pricing immediately upon initialization\n bool enableBoundedPricing;\n /// @notice Whether transient caching of the bounded (collateral, debt) pair is enabled for this asset\n bool enableCaching;\n }\n\n // --- Events ---\n\n /// @notice Emitted when protection is initialized for an asset\n event ProtectionInitialized(\n address indexed asset,\n uint128 minPrice,\n uint128 maxPrice,\n uint64 cooldownPeriod,\n uint256 triggerThreshold\n );\n\n /// @notice Emitted when protection mode is triggered for an asset\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\n\n /// @notice Emitted when protection mode is disabled for an asset\n event ProtectionModeExited(address indexed asset);\n\n /// @notice Emitted when the keeper updates the minimum price for an asset\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\n\n /// @notice Emitted when the keeper updates the maximum price for an asset\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\n\n /// @notice Emitted when the entry threshold is updated for an asset\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\n\n /// @notice Emitted when the exit threshold is updated for an asset\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\n\n /// @notice Emitted when the cooldown period is updated for an asset\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\n\n /// @notice Emitted when an asset's whitelist status changes\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\n\n /// @notice Emitted when the per-asset transient caching flag is toggled\n event CachingEnabledUpdated(address indexed asset, bool oldEnabled, bool newEnabled);\n\n // --- Errors ---\n\n /// @notice Thrown when trying to use or update protection for an asset that has not been initialized\n error MarketNotInitialized(address asset);\n\n /// @notice Thrown when trying to initialize an already initialized market\n error MarketAlreadyInitialized(address asset);\n\n /// @notice Thrown when trying to disable protection that is not active\n error ProtectedPriceInactive(address asset);\n\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\n\n /// @notice Thrown when trying to disable protection before price range has converged\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\n\n /// @notice Thrown when keeper tries to set minPrice above current spot\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\n\n /// @notice Thrown when keeper tries to set maxPrice below current spot\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\n\n /// @notice Thrown when threshold is set below the minimum allowed value\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\n\n /// @notice Thrown when threshold is set above the maximum allowed value\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\n\n /// @notice Thrown when a price exceeds uint128 max\n error PriceExceedsUint128(uint256 price);\n\n /// @notice Thrown when a zero price is provided where a non-zero price is required\n error ZeroPriceNotAllowed();\n\n /// @notice Thrown when trying to initialize protection for VAI\n error VAINotAllowed();\n\n /// @notice Thrown when trying to disable bounded pricing for an asset while protection is active\n error ProtectedPriceActive(address asset);\n\n /// @notice Thrown when the lengths of the arrays are not equal\n error InvalidArrayLength();\n\n /// @notice Thrown when the exit threshold is set at or above the trigger threshold\n error InvalidResetThreshold(uint256 resetThreshold);\n\n /// @notice Thrown when an syncPriceBoundsAndProtections item carries an unsupported action enum value\n error InvalidKeeperAction(uint8 action);\n\n // --- Non-view price functions (update window + trigger protection) ---\n\n /**\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\n\n /**\n * @notice Gets the bounded debt price for a given vToken, updating protection state\n * @param vToken vToken address\n * @return debtPrice The bounded debt price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\n\n /**\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @return debtPrice The bounded debt price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\n\n // --- State update (call before view price reads to populate transient cache) ---\n\n /**\n * @notice Updates the protection state for a given vToken, caching the resolved collateral and debt prices\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\n * reads in the same transaction are served from transient storage. The transient\n * cache is only populated when the asset's `cachingEnabled` flag is `true`.\n * @param vToken vToken address\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function updateProtectionState(address vToken) external;\n\n // --- View price functions (read stored/cached state only) ---\n\n /**\n * @notice Gets the bounded collateral price for a given vToken (view variant)\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\n * falls back to ResilientOracle on cache miss or when caching is disabled.\n * @param vToken vToken address\n * @return price The bounded collateral price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\n */\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\n\n /**\n * @notice Gets the bounded debt price for a given vToken (view variant)\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\n * falls back to ResilientOracle on cache miss or when caching is disabled.\n * @param vToken vToken address\n * @return price The bounded debt price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\n */\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\n\n /**\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\n * @dev Reads from transient cache first when the asset's `cachingEnabled` flag is `true`;\n * falls back to ResilientOracle on cache miss or when caching is disabled.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @return debtPrice The bounded debt price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\n */\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\n\n // --- Keeper functions ---\n\n /**\n * @notice Updates the minimum price in the rolling window for a given asset\n * @param asset The underlying asset address\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\n * @custom:access Only authorized keeper addresses\n * @custom:error ZeroPriceNotAllowed if newMin is zero\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\n * @custom:event MinPriceUpdated\n */\n function updateMinPrice(address asset, uint128 newMin) external;\n\n /**\n * @notice Updates the maximum price in the rolling window for a given asset\n * @param asset The underlying asset address\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\n * @custom:access Only authorized keeper addresses\n * @custom:error ZeroPriceNotAllowed if newMax is zero\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\n * @custom:event MaxPriceUpdated\n */\n function updateMaxPrice(address asset, uint128 newMax) external;\n\n /**\n * @notice Exits protection mode for a given asset once conditions are met\n * @param asset The underlying asset address\n * @custom:access Only authorized monitor/keeper addresses\n * @custom:error ProtectedPriceInactive if protection is not currently active\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\n * @custom:event ProtectionModeExited\n */\n function exitProtectionMode(address asset) external;\n\n /**\n * @notice Dispatches a batch of keeper-only actions (set min, set max, or exit protection) under a single ACM check\n * @dev Each item is processed in array order; any item revert rolls back the whole batch.\n * `value` is interpreted as the new bound price for SetMinPrice / SetMaxPrice and ignored for ExitProtectionMode.\n * Empty `actions` is a no-op success.\n * @param actions The list of keeper actions to apply\n * @custom:access Only authorized keeper addresses\n * @custom:error InvalidKeeperAction if an item carries an unsupported action enum value\n * @custom:error PriceExceedsUint128 if a SetMin/SetMax item value overflows uint128\n * @custom:error ZeroPriceNotAllowed if a SetMin/SetMax item value is zero\n * @custom:error MarketNotInitialized if any referenced asset has not been initialized\n * @custom:error InvalidMinPrice if a SetMinPrice item violates the spot/maxPrice constraints\n * @custom:error InvalidMaxPrice if a SetMaxPrice item violates the spot/minPrice constraints\n * @custom:error ProtectedPriceInactive if an ExitProtectionMode item targets an asset whose protection is not active\n * @custom:error CooldownNotElapsed if an ExitProtectionMode item is submitted before cooldown elapsed\n * @custom:error PriceRangeNotConverged if an ExitProtectionMode item is submitted before window convergence\n * @custom:event MinPriceUpdated, MaxPriceUpdated, ProtectionModeExited\n */\n function syncPriceBoundsAndProtections(KeeperActionItem[] calldata actions) external;\n\n // --- Admin functions (governance-gated) ---\n\n /**\n * @notice Initializes protection parameters for a new asset\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\n * confirming the oracle is live for this asset before it is listed.\n * @param tokenConfig_ Token config input for the asset\n * @custom:access Only Governance\n * @custom:error ZeroAddressNotAllowed if asset is the zero address\n * @custom:error ZeroValueNotAllowed if cooldownPeriod, triggerThreshold, or resetThreshold is zero\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\n * @custom:error VAINotAllowed if asset is the VAI token\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event ProtectionInitialized\n * @custom:event BoundedPricingWhitelistUpdated\n */\n function setTokenConfig(TokenConfigInput calldata tokenConfig_) external;\n\n /**\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\n * @param tokenConfigs_ Array of token config inputs, one per asset\n * @custom:access Only Governance\n * @custom:error InvalidArrayLength if the input array is empty\n * @custom:error ZeroAddressNotAllowed if any asset is the zero address\n * @custom:error ZeroValueNotAllowed if any cooldownPeriod, triggerThreshold, or resetThreshold is zero\n * @custom:error MarketAlreadyInitialized if any asset has already been initialized\n * @custom:error ThresholdBelowMinimum if any triggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if any triggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if any resetThreshold is at or above its triggerThreshold\n * @custom:error VAINotAllowed if any asset is the VAI token\n * @custom:error PriceExceedsUint128 if the spot price for any asset overflows uint128\n * @custom:event ProtectionInitialized for each asset\n * @custom:event BoundedPricingWhitelistUpdated for each asset\n */\n function setTokenConfigs(TokenConfigInput[] calldata tokenConfigs_) external;\n\n /**\n * @notice Sets the cooldown period for an asset\n * @param asset The underlying asset address\n * @param newCooldown The new cooldown period in seconds; must be non-zero\n * @custom:access Only Governance\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:event CooldownPeriodSet\n */\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\n\n /**\n * @notice Sets the trigger and reset thresholds for an asset\n * @param asset The underlying asset address\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\n * @custom:access Only Governance\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\n * @custom:event TriggerThresholdSet if the trigger threshold changed\n * @custom:event ResetThresholdSet if the reset threshold changed\n */\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\n\n /**\n * @notice Sets whether bounded pricing is enabled for an asset\n * @param asset The underlying asset address\n * @param enabled Whether bounded pricing should be enabled for the asset\n * @custom:access Only Governance\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\n * @custom:event BoundedPricingWhitelistUpdated\n */\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\n\n /**\n * @notice Toggles transient caching of the bounded (collateral, debt) pair for an asset\n * @dev When disabled, each view/non-view price call recomputes bounded prices from the\n * live spot instead of reading or writing the transient slots. The initial value is\n * set via the `enableCaching` argument of `setTokenConfig`.\n * @param asset The underlying asset address\n * @param enabled Whether transient caching is enabled for this asset\n * @custom:access Only Governance\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:event CachingEnabledUpdated\n */\n function setCachingEnabled(address asset, bool enabled) external;\n\n // --- View helpers ---\n\n /**\n * @notice Returns the full protection state for an asset\n * @param asset The underlying asset address\n * @return minPrice Lowest price observed in the current window\n * @return maxPrice Highest price observed in the current window\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\n * @return cooldownPeriod Minimum time protection stays active after last trigger\n * @return assetAddr The underlying asset address stored in the struct\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\n * @return cachingEnabled Whether transient caching of the bounded pair is enabled for the asset\n */\n function assetProtectionConfig(\n address asset\n )\n external\n view\n returns (\n uint128 minPrice,\n uint128 maxPrice,\n bool currentlyUsingProtectedPrice,\n bool isBoundedPricingEnabled,\n uint64 lastProtectionTriggeredAt,\n uint64 cooldownPeriod,\n address assetAddr,\n uint128 triggerThreshold,\n uint128 resetThreshold,\n bool cachingEnabled\n );\n\n /**\n * @notice Checks if an asset is whitelisted for bounded pricing\n * @param asset The underlying asset address\n * @return True if the asset is whitelisted\n */\n function isBoundedPricingEnabled(address asset) external view returns (bool);\n\n /**\n * @notice Checks if the asset is currently using the protected (bounded) price\n * @param asset The underlying asset address\n * @return True if the asset is currently using the protected price instead of spot\n */\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\n\n /**\n * @notice Checks if protection can be exited for a given asset\n * @param asset The underlying asset address\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\n */\n function canExitProtection(address asset) external view returns (bool);\n\n /**\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\n * @param index Array index\n * @return The asset address at the given index\n */\n function allAssets(uint256 index) external view returns (address);\n\n /**\n * @notice Returns all currently whitelisted asset addresses\n * @return result Array of whitelisted asset addresses\n */\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\n\n /**\n * @notice Returns all asset addresses that have ever been initialized\n * @return Array of all initialized asset addresses\n */\n function getInitializedAssets() external view returns (address[] memory);\n\n /**\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\n * @param assets Array of asset addresses to check\n * @param proposedMins Keeper's proposed window minimum prices\n * @param proposedMaxs Keeper's proposed window maximum prices\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\n * @custom:error InvalidArrayLength if the input array lengths do not match\n */\n function checkAndGetWindowDrift(\n address[] calldata assets,\n uint128[] calldata proposedMins,\n uint128[] calldata proposedMaxs\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/oracle/contracts/lib/Transient.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nlibrary Transient {\n /**\n * @notice Cache the asset price into transient storage\n * @param key address of the asset\n * @param value asset price\n */\n function cachePrice(bytes32 cacheSlot, address key, uint256 value) internal {\n bytes32 slot = keccak256(abi.encode(cacheSlot, key));\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @notice Read cached price from transient storage\n * @param key address of the asset\n * @return value cached asset price\n */\n function readCachedPrice(bytes32 cacheSlot, address key) internal view returns (uint256 value) {\n bytes32 slot = keccak256(abi.encode(cacheSlot, key));\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title MaxLoopsLimitHelper\n * @author Venus\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\n */\nabstract contract MaxLoopsLimitHelper {\n // Limit for the loops to avoid the DOS\n uint256 public maxLoopsLimit;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when max loops limit is set\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\n\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function _setMaxLoopsLimit(uint256 limit) internal {\n require(limit > maxLoopsLimit, \"Comptroller: Invalid maxLoopsLimit\");\n\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\n maxLoopsLimit = limit;\n\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\n }\n\n /**\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\n * @param len Length of the loops iterate\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\n */\n function _ensureMaxLoops(uint256 len) internal view {\n if (len > maxLoopsLimit) {\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { SECONDS_PER_YEAR } from \"./constants.sol\";\n\nabstract contract TimeManagerV8 {\n /// @notice Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable blocksOrSecondsPerYear;\n\n /// @notice Acknowledges if a contract is time based or not\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n bool public immutable isTimeBased;\n\n /// @notice Stores the current block timestamp or block number depending on isTimeBased\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n function() view returns (uint256) private immutable _getCurrentSlot;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[48] private __gap;\n\n /// @notice Thrown when blocks per year is invalid\n error InvalidBlocksPerYear();\n\n /// @notice Thrown when time based but blocks per year is provided\n error InvalidTimeBasedConfiguration();\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block\n * If timeBased is true than blocksPerYear_ param is ignored as blocksOrSecondsPerYear is set to SECONDS_PER_YEAR\n * @param blocksPerYear_ The number of blocks per year\n * @custom:error InvalidBlocksPerYear is thrown if blocksPerYear entered is zero and timeBased is false\n * @custom:error InvalidTimeBasedConfiguration is thrown if blocksPerYear entered is non zero and timeBased is true\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) {\n if (!timeBased_ && blocksPerYear_ == 0) {\n revert InvalidBlocksPerYear();\n }\n\n if (timeBased_ && blocksPerYear_ != 0) {\n revert InvalidTimeBasedConfiguration();\n }\n\n isTimeBased = timeBased_;\n blocksOrSecondsPerYear = timeBased_ ? SECONDS_PER_YEAR : blocksPerYear_;\n _getCurrentSlot = timeBased_ ? _getBlockTimestamp : _getBlockNumber;\n }\n\n /**\n * @dev Function to simply retrieve block number or block timestamp\n * @return Current block number or block timestamp\n */\n function getBlockNumberOrTimestamp() public view virtual returns (uint256) {\n return _getCurrentSlot();\n }\n\n /**\n * @dev Returns the current timestamp in seconds\n * @return The current timestamp\n */\n function _getBlockTimestamp() private view returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @dev Returns the current block number\n * @return The current block number\n */\n function _getBlockNumber() private view returns (uint256) {\n return block.number;\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/Admin/VBNBAdmin.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IProtocolShareReserve } from \"../external/IProtocolShareReserve.sol\";\nimport { IWBNB } from \"../external/IWBNB.sol\";\nimport { VBNBAdminStorage, VTokenInterface } from \"./VBNBAdminStorage.sol\";\n\n/**\n * @title VBNBAdmin\n * @author Venus\n * @notice This contract is the \"admin\" of the vBNB market, reducing the reserves of the market, sending them to the `ProtocolShareReserve` contract,\n * and allowing the executions of the rest of the privileged functions in the vBNB contract (after checking if the sender has the required permissions).\n */\ncontract VBNBAdmin is ReentrancyGuardUpgradeable, AccessControlledV8, VBNBAdminStorage {\n using SafeERC20Upgradeable for IWBNB;\n\n /// @notice address of vBNB\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n VTokenInterface public immutable vBNB;\n\n /// @notice address of WBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IWBNB public immutable WBNB;\n\n /// @notice Emitted when PSR is updated\n event ProtocolShareReserveUpdated(\n IProtocolShareReserve indexed oldProtocolShareReserve,\n IProtocolShareReserve indexed newProtocolShareReserve\n );\n\n /// @notice Emitted reserves are reduced\n event ReservesReduced(uint256 reduceAmount);\n\n /// @param _vBNB Address of the vBNB contract\n /// @param _WBNB Address of the WBNB token\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(VTokenInterface _vBNB, IWBNB _WBNB) {\n require(address(_WBNB) != address(0), \"WBNB address invalid\");\n require(address(_vBNB) != address(0), \"vBNB address invalid\");\n\n vBNB = _vBNB;\n WBNB = _WBNB;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @notice Used to initialize non-immutable variables\n function initialize(\n IProtocolShareReserve _protocolShareReserve,\n address accessControlManager\n ) external initializer {\n require(address(_protocolShareReserve) != address(0), \"PSR address invalid\");\n protocolShareReserve = _protocolShareReserve;\n\n __ReentrancyGuard_init();\n __AccessControlled_init(accessControlManager);\n }\n\n /**\n * @notice PSR setter.\n * @param protocolShareReserve_ Address of the PSR contract\n * @custom:access Only owner (Governance)\n * @custom:event Emits ProtocolShareReserveUpdated event.\n */\n function setProtocolShareReserve(IProtocolShareReserve protocolShareReserve_) external onlyOwner {\n require(address(protocolShareReserve_) != address(0), \"PSR address invalid\");\n emit ProtocolShareReserveUpdated(protocolShareReserve, protocolShareReserve_);\n protocolShareReserve = protocolShareReserve_;\n }\n\n /**\n * @notice Reduce reserves of vBNB, wrap them and send them to the PSR contract\n * @param reduceAmount amount of reserves to reduce\n * @custom:event Emits ReservesReduced event.\n */\n function reduceReserves(uint reduceAmount) external nonReentrant {\n require(vBNB._reduceReserves(reduceAmount) == 0, \"reduceReserves failed\");\n _wrapBNB();\n\n uint256 balance = WBNB.balanceOf(address(this));\n WBNB.safeTransfer(address(protocolShareReserve), balance);\n protocolShareReserve.updateAssetsState(\n vBNB.comptroller(),\n address(WBNB),\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit ReservesReduced(reduceAmount);\n }\n\n /**\n * @notice Sets the interest rate model of the vBNB contract\n * @param newInterestRateModel Address of the new interest rate model\n * @custom:access Controlled by ACM\n */\n function setInterestRateModel(address newInterestRateModel) public returns (uint256) {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n return vBNB._setInterestRateModel(newInterestRateModel);\n }\n\n /**\n * @notice Wraps BNB into WBNB\n */\n function _wrapBNB() internal {\n uint256 bnbBalance = address(this).balance;\n WBNB.deposit{ value: bnbBalance }();\n }\n\n /**\n * @notice Invoked when BNB is sent to this contract\n * @custom:access Only vBNB is considered a valid sender\n */\n receive() external payable {\n require(msg.sender == address(vBNB), \"only vBNB can send BNB to this contract\");\n }\n\n /**\n * @notice Invoked when called function does not exist in the contract. The function will be executed in the vBNB contract.\n * @custom:access Only owner (Governance)\n */\n fallback(bytes calldata data) external payable onlyOwner returns (bytes memory) {\n (bool ok, bytes memory res) = address(vBNB).call{ value: msg.value }(data);\n require(ok, \"call failed\");\n return res;\n }\n}\n" + }, + "contracts/Admin/VBNBAdminStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IProtocolShareReserve } from \"../external/IProtocolShareReserve.sol\";\n\ninterface VTokenInterface {\n function _reduceReserves(uint reduceAmount) external returns (uint);\n\n function _acceptAdmin() external returns (uint);\n\n function comptroller() external returns (address);\n\n function _setInterestRateModel(address newInterestRateModel) external returns (uint);\n}\n\ncontract VBNBAdminStorage {\n /// @notice address of protocol share reserve contract\n IProtocolShareReserve public protocolShareReserve;\n\n /// @dev gap to prevent collision in inheritence\n uint256[49] private __gap;\n}\n" + }, + "contracts/Comptroller/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { VAIControllerInterface } from \"../Tokens/VAI/VAIControllerInterface.sol\";\nimport { WeightFunction } from \"./Diamond/interfaces/IFacetBase.sol\";\n\nenum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n}\n\ninterface ComptrollerInterface {\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() external pure returns (bool);\n\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\n\n function exitMarket(address vToken) external returns (uint);\n\n /*** Policy Hooks ***/\n\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function executeFlashLoan(\n address payable onBehalf,\n address payable receiver,\n VToken[] calldata vTokens,\n uint256[] calldata underlyingAmounts,\n bytes calldata param\n ) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external returns (uint);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function liquidateCalculateSeizeTokens(\n address borrower,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function getXVSAddress() external view returns (address);\n\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\n\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function claimVenus(address) external;\n\n function venusAccrued(address) external view returns (uint);\n\n function venusSupplySpeeds(address) external view returns (uint);\n\n function venusBorrowSpeeds(address) external view returns (uint);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function venusSupplierIndex(address, address) external view returns (uint);\n\n function venusInitialIndex() external view returns (uint224);\n\n function venusBorrowerIndex(address, address) external view returns (uint);\n\n function venusBorrowState(address) external view returns (uint224, uint32);\n\n function venusSupplyState(address) external view returns (uint224, uint32);\n\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\n\n function vaiController() external view returns (VAIControllerInterface);\n\n function protocolPaused() external view returns (bool);\n\n function actionPaused(address market, Action action) external view returns (bool);\n\n function mintedVAIs(address user) external view returns (uint);\n\n function vaiMintRate() external view returns (uint);\n\n function authorizedFlashLoan(address account) external view returns (bool);\n\n function userPoolId(address account) external view returns (uint96);\n\n function getLiquidationIncentive(address vToken) external view returns (uint256);\n\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\n\n function getEffectiveLtvFactor(\n address account,\n address vToken,\n WeightFunction weightingStrategy\n ) external view returns (uint256);\n\n function lastPoolId() external view returns (uint96);\n\n function corePoolId() external pure returns (uint96);\n\n function pools(\n uint96 poolId\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\n\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\n\n function poolMarkets(\n uint96 poolId,\n address vToken\n )\n external\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n );\n\n function isFlashLoanPaused() external view returns (bool);\n}\n\ninterface IVAIVault {\n function updatePendingRewards() external;\n}\n\ninterface IComptroller {\n /*** Treasury Data ***/\n function treasuryAddress() external view returns (address);\n\n function treasuryPercent() external view returns (uint);\n}\n" + }, + "contracts/Comptroller/ComptrollerLensInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { WeightFunction } from \"./Diamond/interfaces/IFacetBase.sol\";\n\ninterface ComptrollerLensInterface {\n function liquidateCalculateSeizeTokens(\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function liquidateCalculateSeizeTokens(\n address borrower,\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function liquidateVAICalculateSeizeTokens(\n address comptroller,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function getHypotheticalAccountLiquidity(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount,\n WeightFunction weightingStrategy\n ) external view returns (uint, uint, uint);\n}\n" + }, + "contracts/Comptroller/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\nimport { PoolMarketId } from \"./Types/PoolMarketId.sol\";\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { VAIControllerInterface } from \"../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterface } from \"./ComptrollerLensInterface.sol\";\nimport { IPrime } from \"../Tokens/Prime/IPrime.sol\";\n\ncontract UnitrollerAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of Unitroller\n */\n address public comptrollerImplementation;\n\n /**\n * @notice Pending brains of Unitroller\n */\n address public pendingComptrollerImplementation;\n}\n\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\n /**\n * @notice Oracle which gives the price of any given asset\n */\n ResilientOracleInterface public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\n */\n uint256 private _oldLiquidationIncentiveMantissa;\n\n /**\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\n */\n uint256 public maxAssets;\n\n /**\n * @notice Per-account mapping of \"assets you are in\", capped by maxAssets\n */\n mapping(address => VToken[]) public accountAssets;\n\n struct Market {\n /// @notice Whether or not this market is listed\n bool isListed;\n /**\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\n * For instance, 0.9 to allow borrowing 90% of collateral value.\n * Must be between 0 and 1, and stored as a mantissa.\n */\n uint256 collateralFactorMantissa;\n /// @notice Per-market mapping of \"accounts in this asset\" (used for Core Pool only)\n mapping(address => bool) accountMembership;\n /// @notice Whether or not this market receives XVS\n bool isVenus;\n /**\n * @notice Multiplier representing the collateralization after which the borrow is eligible\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\n * value. Must be between 0 and collateral factor, stored as a mantissa.\n */\n uint256 liquidationThresholdMantissa;\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\n uint256 liquidationIncentiveMantissa;\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\n uint96 poolId;\n /// @notice Flag to restrict borrowing in certain pools/emodes.\n bool isBorrowAllowed;\n }\n\n /**\n * @notice Mapping of PoolMarketId -> Market metadata\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\n */\n mapping(PoolMarketId => Market) internal _poolMarkets;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n address public pauseGuardian;\n\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\n bool private _mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool private _borrowGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal transferGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal seizeGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal borrowGuardianPaused;\n\n struct VenusMarketState {\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\n uint224 index;\n /// @notice The block number the index was last updated at\n uint32 block;\n }\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice The rate at which the flywheel distributes XVS, per block\n uint256 internal venusRate;\n\n /// @notice The portion of venusRate that each market currently receives\n mapping(address => uint256) internal venusSpeeds;\n\n /// @notice The Venus market supply state for each market\n mapping(address => VenusMarketState) public venusSupplyState;\n\n /// @notice The Venus market borrow state for each market\n mapping(address => VenusMarketState) public venusBorrowState;\n\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\n\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\n\n /// @notice The XVS accrued but not yet transferred to each user\n mapping(address => uint256) public venusAccrued;\n\n /// @notice The Address of VAIController\n VAIControllerInterface public vaiController;\n\n /// @notice The minted VAI amount to each user\n mapping(address => uint256) public mintedVAIs;\n\n /// @notice VAI Mint Rate as a percentage\n uint256 public vaiMintRate;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n bool public mintVAIGuardianPaused;\n bool public repayVAIGuardianPaused;\n\n /**\n * @notice Pause/Unpause whole protocol actions\n */\n bool public protocolPaused;\n\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\n uint256 private venusVAIRate;\n}\n\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\n uint256 public venusVAIVaultRate;\n\n // address of VAI Vault\n address public vaiVaultAddress;\n\n // start block of release to VAI Vault\n uint256 public releaseStartBlock;\n\n // minimum release amount to VAI Vault\n uint256 public minReleaseAmount;\n}\n\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\n address public borrowCapGuardian;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\n mapping(address => uint256) public borrowCaps;\n}\n\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\n /// @notice Treasury Guardian address\n address public treasuryGuardian;\n\n /// @notice Treasury address\n address public treasuryAddress;\n\n /// @notice Fee percent of accrued interest with decimal 18\n uint256 public treasuryPercent;\n}\n\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\n mapping(address => uint256) private venusContributorSpeeds;\n\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\n mapping(address => uint256) private lastContributorBlock;\n}\n\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\n address public liquidatorContract;\n}\n\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\n ComptrollerLensInterface public comptrollerLens;\n}\n\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\n mapping(address => uint256) public supplyCaps;\n}\n\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\n /// @notice AccessControlManager address\n address internal accessControl;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\n}\n\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public venusBorrowSpeeds;\n\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public venusSupplySpeeds;\n}\n\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\n mapping(address => mapping(address => bool)) public approvedDelegates;\n}\n\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\n mapping(address => bool) public isForcedLiquidationEnabled;\n}\n\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\n }\n\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\n // facet addresses\n address[] internal _facetAddresses;\n}\n\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\n /// @notice Prime token address\n IPrime public prime;\n}\n\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\n}\n\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\n /// @notice The XVS token contract address\n address internal xvs;\n\n /// @notice The XVS vToken contract address\n address internal xvsVToken;\n}\n\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\n struct PoolData {\n /// @notice label for the pool\n string label;\n /// @notice List of vToken addresses associated with this pool\n address[] vTokens;\n /**\n * @notice Whether the pool is active and can be entered. If set to false,\n * new entries are disabled and existing accounts fall back to core pool values\n */\n bool isActive;\n /**\n * @notice Whether core pool risk factors can be used as fallback when the market\n * is not configured in the specific pool, falls back when set to true\n */\n bool allowCorePoolFallback;\n }\n\n /**\n * @notice Tracks the selected pool for each user\n * @dev\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\n * - A value of `0` represents the default core pool (legacy behavior)\n */\n mapping(address => uint96) public userPoolId;\n\n /**\n * @notice Mapping of pool ID to its corresponding metadata and configuration\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\n * Not updated for the Core Pool (`poolId = 0`)\n */\n mapping(uint96 => PoolData) public pools;\n\n /**\n * @notice Counter used to generate unique pool IDs\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\n */\n uint96 public lastPoolId;\n}\n\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\n /// @notice Mapping of accounts authorized to execute flash loans\n mapping(address => bool) public authorizedFlashLoan;\n\n /// @notice Whether flash loans are paused system-wide\n bool public flashLoanPaused;\n}\n\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\n IDeviationBoundedOracle public deviationBoundedOracle;\n}\n" + }, + "contracts/Comptroller/Diamond/Diamond.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IDiamondCut } from \"./interfaces/IDiamondCut.sol\";\nimport { Unitroller } from \"../Unitroller.sol\";\nimport { ComptrollerV19Storage } from \"../ComptrollerStorage.sol\";\n\n/**\n * @title Diamond\n * @author Venus\n * @notice This contract contains functions related to facets\n */\ncontract Diamond is IDiamondCut, ComptrollerV19Storage {\n /// @notice Emitted when functions are added, replaced or removed to facets\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut);\n\n struct Facet {\n address facetAddress;\n bytes4[] functionSelectors;\n }\n\n /**\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\n * @param unitroller Address of the unitroller\n */\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n /**\n * @notice To add function selectors to the facet's mapping\n * @dev Allows the contract admin to add function selectors\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\n */\n function diamondCut(IDiamondCut.FacetCut[] memory diamondCut_) public {\n require(msg.sender == admin, \"only unitroller admin can\");\n libDiamondCut(diamondCut_);\n }\n\n /**\n * @notice Get all function selectors mapped to the facet address\n * @param facet Address of the facet\n * @return selectors Array of function selectors\n */\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\n return _facetFunctionSelectors[facet].functionSelectors;\n }\n\n /**\n * @notice Get facet position in the _facetFunctionSelectors through facet address\n * @param facet Address of the facet\n * @return Position of the facet\n */\n function facetPosition(address facet) external view returns (uint256) {\n return _facetFunctionSelectors[facet].facetAddressPosition;\n }\n\n /**\n * @notice Get all facet addresses\n * @return facetAddresses Array of facet addresses\n */\n function facetAddresses() external view returns (address[] memory) {\n return _facetAddresses;\n }\n\n /**\n * @notice Get facet address and position through function selector\n * @param functionSelector function selector\n * @return FacetAddressAndPosition facet address and position\n */\n function facetAddress(\n bytes4 functionSelector\n ) external view returns (ComptrollerV19Storage.FacetAddressAndPosition memory) {\n return _selectorToFacetAndPosition[functionSelector];\n }\n\n /**\n * @notice Get all facets address and their function selector\n * @return facets_ Array of Facet\n */\n function facets() external view returns (Facet[] memory) {\n uint256 facetsLength = _facetAddresses.length;\n Facet[] memory facets_ = new Facet[](facetsLength);\n for (uint256 i; i < facetsLength; ++i) {\n address facet = _facetAddresses[i];\n facets_[i].facetAddress = facet;\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\n }\n return facets_;\n }\n\n /**\n * @notice To add function selectors to the facets' mapping\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\n */\n function libDiamondCut(IDiamondCut.FacetCut[] memory diamondCut_) internal {\n uint256 diamondCutLength = diamondCut_.length;\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\n IDiamondCut.FacetCutAction action = diamondCut_[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n }\n emit DiamondCut(diamondCut_);\n }\n\n /**\n * @notice Add function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to add in the mapping\n */\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress == address(0), \"LibDiamondCut: Can't add function that already exists\");\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to replace in the mapping\n */\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress != facetAddress, \"LibDiamondCut: Can't replace function with same function\");\n removeFunction(oldFacetAddress, selector);\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Remove function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to remove in the mapping\n */\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n uint256 functionSelectorsLength = functionSelectors.length;\n require(functionSelectorsLength != 0, \"LibDiamondCut: No selectors in facet to cut\");\n // if function does not exist then do nothing and revert\n require(facetAddress == address(0), \"LibDiamondCut: Remove facet address must be address(0)\");\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n removeFunction(oldFacetAddress, selector);\n }\n }\n\n /**\n * @notice Add new facet to the proxy\n * @param facetAddress Address of the facet\n */\n function addFacet(address facetAddress) internal {\n enforceHasContractCode(facetAddress, \"Diamond: New facet has no code\");\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\n _facetAddresses.push(facetAddress);\n }\n\n /**\n * @notice Add function selector to the facet's address mapping\n * @param selector funciton selector need to be added\n * @param selectorPosition funciton selector position\n * @param facetAddress Address of the facet\n */\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\n }\n\n /**\n * @notice Remove function selector to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param selector function selectors need to remove in the mapping\n */\n function removeFunction(address facetAddress, bytes4 selector) internal {\n require(facetAddress != address(0), \"LibDiamondCut: Can't remove function that doesn't exist\");\n\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\n // if not the same then replace selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\n delete _selectorToFacetAndPosition[selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\n }\n _facetAddresses.pop();\n delete _facetFunctionSelectors[facetAddress];\n }\n }\n\n /**\n * @dev Ensure that the given address has contract code deployed\n * @param _contract The address to check for contract code\n * @param _errorMessage The error message to display if the contract code is not deployed\n */\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\n uint256 contractSize;\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize != 0, _errorMessage);\n }\n\n // Find facet for function that is called and execute the\n // function if a facet is found and return any value.\n fallback() external {\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\n require(facet != address(0), \"Diamond: Function does not exist\");\n // Execute public function from facet using delegatecall and return any value.\n assembly {\n // copy function selector and any arguments\n calldatacopy(0, 0, calldatasize())\n // execute function call using the facet\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\n // get any return value\n returndatacopy(0, 0, returndatasize())\n // return any return value or error back to the caller\n switch result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/DiamondConsolidated.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { MarketFacet } from \"./facets/MarketFacet.sol\";\nimport { PolicyFacet } from \"./facets/PolicyFacet.sol\";\nimport { RewardFacet } from \"./facets/RewardFacet.sol\";\nimport { SetterFacet } from \"./facets/SetterFacet.sol\";\nimport { FlashLoanFacet } from \"./facets/FlashLoanFacet.sol\";\nimport { Diamond } from \"./Diamond.sol\";\n\n/**\n * @title DiamondConsolidated\n * @author Venus\n * @notice This contract contains the functions defined in the different facets of the Diamond, plus the getters to the public variables.\n * This contract cannot be deployed, due to its size. Its main purpose is to allow the easy generation of an ABI and the typechain to interact with the\n * Unitroller contract in a simple way\n */\ncontract DiamondConsolidated is Diamond, MarketFacet, PolicyFacet, RewardFacet, SetterFacet, FlashLoanFacet {}\n" + }, + "contracts/Comptroller/Diamond/facets/FacetBase.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { ComptrollerErrorReporter } from \"../../../Utils/ErrorReporter.sol\";\nimport { ExponentialNoError } from \"../../../Utils/ExponentialNoError.sol\";\nimport { IVAIVault, Action } from \"../../../Comptroller/ComptrollerInterface.sol\";\nimport { ComptrollerV19Storage } from \"../../../Comptroller/ComptrollerStorage.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\nimport { IFacetBase, WeightFunction } from \"../interfaces/IFacetBase.sol\";\n\n/**\n * @title FacetBase\n * @author Venus\n * @notice This facet contract contains functions related to access and checks\n */\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\n using SafeERC20 for IERC20;\n\n /// @notice The initial Venus index for a market\n uint224 public constant venusInitialIndex = 1e36;\n // poolId for core Pool\n uint96 public constant corePoolId = 0;\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\n // closeFactorMantissa must not exceed this value\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when XVS is distributed to VAI Vault\n event DistributedVAIVaultVenus(uint256 amount);\n\n /// @notice Reverts if the protocol is paused\n function checkProtocolPauseState() internal view {\n require(!protocolPaused, \"protocol is paused\");\n }\n\n /// @notice Reverts if a certain action is paused on a market\n function checkActionPauseState(address market, Action action) internal view {\n require(!actionPaused(market, action), \"action is paused\");\n }\n\n /// @notice Reverts if the caller is not admin\n function ensureAdmin() internal view {\n require(msg.sender == admin, \"only admin can\");\n }\n\n /// @notice Checks the passed address is nonzero\n function ensureNonzeroAddress(address someone) internal pure {\n require(someone != address(0), \"can't be zero address\");\n }\n\n /// @notice Reverts if the market is not listed\n function ensureListed(Market storage market) internal view {\n require(market.isListed, \"market not listed\");\n }\n\n /// @notice Reverts if the caller is neither admin nor the passed address\n function ensureAdminOr(address privilegedAddress) internal view {\n require(msg.sender == admin || msg.sender == privilegedAddress, \"access denied\");\n }\n\n /// @notice Checks the caller is allowed to call the specified fuction\n function ensureAllowed(string memory functionSig) internal view {\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \"access denied\");\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param action Action id\n * @param market vToken address\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][uint256(action)];\n }\n\n /**\n * @notice Get the latest block number\n */\n function getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Get the latest block number with the safe32 check\n */\n function getBlockNumberAsUint32() internal view returns (uint32) {\n return safe32(getBlockNumber(), \"block # > 32 bits\");\n }\n\n /**\n * @notice Transfer XVS to VAI Vault\n */\n function releaseToVault() internal {\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\n return;\n }\n\n IERC20 xvs_ = IERC20(xvs);\n\n uint256 xvsBalance = xvs_.balanceOf(address(this));\n if (xvsBalance == 0) {\n return;\n }\n\n uint256 actualAmount;\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\n // releaseAmount = venusVAIVaultRate * deltaBlocks\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\n\n if (xvsBalance >= releaseAmount_) {\n actualAmount = releaseAmount_;\n } else {\n actualAmount = xvsBalance;\n }\n\n if (actualAmount < minReleaseAmount) {\n return;\n }\n\n releaseStartBlock = getBlockNumber();\n\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\n emit DistributedVAIVaultVenus(actualAmount);\n\n IVAIVault(vaiVaultAddress).updatePendingRewards();\n }\n\n /**\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\n * exceeds the threshold.\n * @param account The account to determine liquidity for\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param redeemTokens The number of vTokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\n * @return err Possible error code\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\n */\n function getHypotheticalAccountLiquidityInternal(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n WeightFunction weightingStrategy\n ) internal returns (Error, uint256, uint256) {\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\n // Required on the CF path so bounded prices are computed once and reused\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\n // within the same transaction.\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\n _updateProtectionStates(account);\n }\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\n address(this),\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount,\n weightingStrategy\n );\n return (Error(err), liquidity, shortfall);\n }\n\n /**\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\n * the transient cache. Use this only in external view functions where state mutation is not\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\n * was already executed earlier in the same transaction, the DBO transient cache will already be\n * populated and this function will read from it gas-efficiently — no recomputation occurs.\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\n * scratch on each call; results are still correct but cost more gas.\n * @param account The account to determine liquidity for\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param redeemTokens The number of vTokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\n * @return err Possible error code\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\n */\n function getHypotheticalAccountLiquidityInternalView(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n WeightFunction weightingStrategy\n ) internal view returns (Error, uint256, uint256) {\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\n address(this),\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount,\n weightingStrategy\n );\n return (Error(err), liquidity, shortfall);\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n * @return Success indicator for whether the market was entered\n */\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\n ensureListed(marketToJoin);\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return Error.NO_ERROR;\n }\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n\n return Error.NO_ERROR;\n }\n\n /**\n * @notice Checks for the user is allowed to redeem tokens\n * @param vToken Address of the market\n * @param redeemer Address of the user\n * @param redeemTokens Amount of tokens to redeem\n * @return Success indicator for redeem is allowed or not\n */\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\n ensureListed(getCorePoolMarket(vToken));\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\n return uint256(Error.NO_ERROR);\n }\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Returns the XVS address\n * @return The address of XVS token\n */\n function getXVSAddress() external view returns (address) {\n return xvs;\n }\n\n /**\n * @notice Returns the unique market index for the given poolId and vToken pair\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\n * maintaining backward compatibility with legacy mappings\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\n * @param poolId The ID of the pool\n * @param vToken The address of the market (vToken)\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\n */\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\n }\n\n /**\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\n * @param vToken The vToken address for which the market details are requested\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\n */\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\n }\n\n /**\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\n * @param account The account whose collateral assets need protection state updates\n */\n function _updateProtectionStates(address account) internal {\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\n VToken[] memory assets = accountAssets[account];\n uint256 len = assets.length;\n for (uint256 i; i < len; ++i) {\n boundedOracle.updateProtectionState(address(assets[i]));\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IFlashLoanFacet } from \"../interfaces/IFlashLoanFacet.sol\";\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { FacetBase } from \"./FacetBase.sol\";\nimport { IFlashLoanReceiver } from \"../../../FlashLoan/interfaces/IFlashLoanReceiver.sol\";\nimport { ReentrancyGuardTransient } from \"../../../Utils/ReentrancyGuardTransient.sol\";\n\n/**\n * @title FlashLoanFacet\n * @author Venus\n * @notice This facet contains all the methods related to flash loans\n * @dev This contract implements flash loan functionality allowing users to borrow assets temporarily\n * within a single transaction. Users can borrow multiple assets simultaneously and have the\n * flexibility to repay partially, with unpaid balances automatically converted to debt positions.\n * The contract supports protocol fee collection and integrates with the Venus lending protocol.\n */\ncontract FlashLoanFacet is IFlashLoanFacet, FacetBase, ReentrancyGuardTransient {\n /// @notice Maximum number of assets that can be flash loaned in a single transaction\n uint256 public constant MAX_FLASHLOAN_ASSETS = 200;\n\n /// @notice Emitted when the flash loan is successfully executed\n event FlashLoanExecuted(address indexed receiver, VToken[] assets, uint256[] amounts);\n\n /// @notice Emitted when a flash loan is repaid (fully or partially) and shows debt position status\n event FlashLoanRepaid(\n address indexed receiver,\n address indexed onBehalf,\n address indexed asset,\n uint256 repaidAmount,\n uint256 remainingDebt\n );\n\n /**\n * @notice Executes a flashLoan operation with the requested assets.\n * @dev Transfers the specified assets to the receiver contract and handles repayment.\n * @param onBehalf The address of the user whose debt position will be used for the flashLoan.\n * @param receiver The address of the contract that will receive the flashLoan amount and execute the operation.\n * @param vTokens The addresses of the vToken assets to be loaned.\n * @param underlyingAmounts The amounts of each underlying assets to be loaned.\n * @param param The bytes passed in the executeOperation call.\n * @custom:error FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.\n * @custom:error FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.\n * @custom:error InvalidAmount is thrown if the requested amount is zero.\n * @custom:error TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.\n * @custom:error NoAssetsRequested is thrown if no assets are requested for the flash loan.\n * @custom:error InvalidFlashLoanParams is thrown if the flash loan params are invalid.\n * @custom:error MarketNotListed is thrown if the specified vToken market is not listed.\n * @custom:error SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.\n * @custom:error NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\n * @custom:event Emits FlashLoanExecuted on success\n */\n function executeFlashLoan(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n bytes memory param\n ) external nonReentrant {\n if (flashLoanPaused) {\n revert FlashLoanPausedSystemWide();\n }\n\n ensureNonzeroAddress(onBehalf);\n\n uint256 len = vTokens.length;\n Market storage market;\n\n // vTokens array must not be empty\n if (len == 0) {\n revert NoAssetsRequested();\n }\n // Add maximum array length check to prevent gas limit issues\n if (len > MAX_FLASHLOAN_ASSETS) {\n revert TooManyAssetsRequested(len, MAX_FLASHLOAN_ASSETS);\n }\n\n // All arrays must have the same length and not be zero\n if (len != underlyingAmounts.length) {\n revert InvalidFlashLoanParams();\n }\n\n for (uint256 i; i < len; ++i) {\n market = getCorePoolMarket(address(vTokens[i]));\n if (!market.isListed) {\n revert MarketNotListed(address(vTokens[i]));\n }\n if (!(vTokens[i]).isFlashLoanEnabled()) {\n revert FlashLoanNotEnabled();\n }\n if (underlyingAmounts[i] == 0) {\n revert InvalidAmount();\n }\n }\n\n ensureNonzeroAddress(receiver);\n\n if (!authorizedFlashLoan[msg.sender]) {\n revert SenderNotAuthorizedForFlashLoan(msg.sender);\n }\n\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\n revert NotAnApprovedDelegate();\n }\n\n // Execute flash loan phases\n _executeFlashLoanPhases(onBehalf, receiver, vTokens, underlyingAmounts, param);\n\n emit FlashLoanExecuted(receiver, vTokens, underlyingAmounts);\n }\n\n /**\n * @notice Executes all flash loan phases in sequence\n * @dev Orchestrates the complete flash loan process through three phases:\n * Phase 1: Calculate fees and transfer assets to receiver\n * Phase 2: Execute custom operations on receiver contract\n * Phase 3: Handle repayment and debt position creation\n * @param onBehalf The address whose debt position will be used for any unpaid flash loan balance\n * @param receiver The address of the contract receiving the flash loan\n * @param vTokens Array of vToken contracts for the assets being borrowed\n * @param underlyingAmounts Array of amounts being borrowed for each asset\n * @param param Additional parameters passed to the receiver contract\n */\n function _executeFlashLoanPhases(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n bytes memory param\n ) internal {\n FlashLoanFee memory flashLoanData;\n //Cache array length\n uint256 vTokensLength = vTokens.length;\n // Initialize arrays\n flashLoanData.totalFees = new uint256[](vTokensLength);\n flashLoanData.protocolFees = new uint256[](vTokensLength);\n\n // Phase 1: Calculate fees and transfer assets\n _executePhase1(receiver, vTokens, underlyingAmounts, flashLoanData);\n // Phase 2: Execute operations on receiver contract\n uint256[] memory tokensApproved = _executePhase2(\n onBehalf,\n receiver,\n vTokens,\n underlyingAmounts,\n flashLoanData.totalFees,\n param\n );\n // Phase 3: Handles repayment\n _executePhase3(onBehalf, receiver, vTokens, underlyingAmounts, tokensApproved, flashLoanData);\n }\n\n /**\n * @notice Phase 1: Calculate fees and transfer assets to receiver\n * @dev For each requested asset:\n * - Calculates total fee and protocol fee using the vToken's fee structure\n * - Transfers the requested amount from the vToken to the receiver\n * - Updates flash loan tracking in the vToken contract\n * @param receiver The address receiving the flash loan assets\n * @param vTokens Array of vToken contracts for the assets being borrowed\n * @param underlyingAmounts Array of amounts being borrowed for each asset\n * @param flashLoanData Struct containing fee arrays to be populated\n */\n function _executePhase1(\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n FlashLoanFee memory flashLoanData\n ) internal {\n //Cache array length\n uint256 vTokensLength = vTokens.length;\n\n for (uint256 i; i < vTokensLength; ++i) {\n (flashLoanData.totalFees[i], flashLoanData.protocolFees[i]) = vTokens[i].calculateFlashLoanFee(\n underlyingAmounts[i]\n );\n\n // Transfer the asset to receiver\n vTokens[i].transferOutUnderlyingFlashLoan(receiver, underlyingAmounts[i]);\n }\n }\n\n /**\n * @notice Phase 2: Execute custom operations on receiver contract\n * @dev Calls the receiver contract's executeOperation function, allowing it to perform\n * custom logic with the borrowed assets. The receiver must return success status\n * and specify repayment amounts for each asset.\n * @param onBehalf The address whose debt position will be used for any unpaid balance\n * @param receiver The address of the contract executing custom operations\n * @param vTokens Array of vToken contracts for the borrowed assets\n * @param underlyingAmounts Array of amounts that were borrowed for each asset\n * @param totalFees Array of total fees for each borrowed asset\n * @param param Additional parameters passed to the receiver's executeOperation function\n * @return tokensApproved Array of amounts the receiver approved for repayment\n * @custom:error ExecuteFlashLoanFailed is thrown if the receiver's executeOperation returns false\n */\n function _executePhase2(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n uint256[] memory totalFees,\n bytes memory param\n ) internal returns (uint256[] memory) {\n (bool success, uint256[] memory tokensApproved) = IFlashLoanReceiver(receiver).executeOperation(\n vTokens,\n underlyingAmounts,\n totalFees,\n msg.sender,\n onBehalf,\n param\n );\n\n if (!success) {\n revert ExecuteFlashLoanFailed();\n }\n return tokensApproved;\n }\n\n /**\n * @notice Phase 3: Handles repayment based on full or partial repayment\n * @dev Processes repayment for each asset in the flash loan:\n * - Ensures minimum fee repayment for each asset\n * - Creates debt positions for any unpaid balances\n * - Handles protocol fee distribution automatically\n * @param onBehalf The address whose debt position will be used for any unpaid balance\n * @param receiver The address providing the repayment\n * @param vTokens Array of vToken contracts for the borrowed assets\n * @param underlyingAmounts Array of amounts that were originally borrowed for each asset\n * @param underlyingAmountsToRepay Array of amounts to be repaid for each asset\n * @param flashLoanData Struct containing calculated fees for each asset\n */\n function _executePhase3(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n uint256[] memory underlyingAmountsToRepay,\n FlashLoanFee memory flashLoanData\n ) internal {\n //Cache array length\n uint256 vTokensLength = vTokens.length;\n\n for (uint256 i; i < vTokensLength; ++i) {\n _handleFlashLoan(\n vTokens[i],\n onBehalf,\n receiver,\n underlyingAmounts[i],\n underlyingAmountsToRepay[i],\n flashLoanData.totalFees[i],\n flashLoanData.protocolFees[i]\n );\n }\n }\n\n /**\n * @notice Handles the repayment and fee logic for a flash loan.\n * @dev This function processes flash loan repayment with the following logic:\n * 1. Ensures the repayment amount is at least equal to the total fee (minimum requirement).\n * 2. Caps the repayment to prevent over-repayment (borrowedAmount + totalFee maximum).\n * 3. Transfers the actual repayment amount from the receiver to the vToken.\n * 4. If repayment is less than the full amount (borrowedAmount + totalFee), creates a debt position\n * for the unpaid balance on the onBehalf address.\n * 5. Protocol fees are automatically handled within the transferInUnderlyingFlashLoan function.\n * @param vToken The vToken contract for the asset being flash loaned.\n * @param onBehalf The address whose debt position will be used if there is any unpaid flash loan balance.\n * @param receiver The address that received the flash loan and is providing the repayment.\n * @param borrowedAmount The original amount that was borrowed (passed from underlyingAmounts).\n * @param repayAmount The amount being repaid by the receiver (may be partial or full repayment).\n * @param totalFee The total fee charged for the flash loan (minimum required repayment).\n * @param protocolFee The portion of the total fee allocated to the protocol.\n * @custom:error NotEnoughRepayment is thrown if repayAmount is less than the minimum required fee.\n * @custom:error FailedToCreateDebtPosition is thrown if debt position creation fails for unpaid balance.\n */\n function _handleFlashLoan(\n VToken vToken,\n address payable onBehalf,\n address payable receiver,\n uint256 borrowedAmount,\n uint256 repayAmount,\n uint256 totalFee,\n uint256 protocolFee\n ) internal {\n uint256 maxExpectedRepayment = borrowedAmount + totalFee;\n uint256 actualRepayAmount = repayAmount > maxExpectedRepayment ? maxExpectedRepayment : repayAmount;\n\n if (actualRepayAmount < totalFee) {\n revert NotEnoughRepayment(actualRepayAmount, totalFee);\n }\n\n // Transfer repayment (this will handle the protocol fee as well)\n uint256 actualAmountTransferred = vToken.transferInUnderlyingFlashLoan(\n receiver,\n actualRepayAmount,\n totalFee,\n protocolFee\n );\n\n // Default for full repayment\n uint256 leftUnpaidBalance;\n\n if (maxExpectedRepayment > actualAmountTransferred) {\n // If there is any unpaid balance, it becomes an ongoing debt\n leftUnpaidBalance = maxExpectedRepayment - actualAmountTransferred;\n\n uint256 debtError = vToken.flashLoanDebtPosition(onBehalf, leftUnpaidBalance);\n if (debtError != 0) {\n revert FailedToCreateDebtPosition();\n }\n }\n\n // Emit event for partial repayment with debt position creation\n emit FlashLoanRepaid(\n receiver,\n onBehalf,\n address(vToken.underlying()),\n actualAmountTransferred,\n leftUnpaidBalance\n );\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/MarketFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { IMarketFacet } from \"../interfaces/IMarketFacet.sol\";\nimport { FacetBase } from \"./FacetBase.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\nimport { WeightFunction } from \"../interfaces/IFacetBase.sol\";\n\n/**\n * @title MarketFacet\n * @author Venus\n * @dev This facet contains all the methods related to the market's management in the pool\n * @notice This facet contract contains functions regarding markets\n */\ncontract MarketFacet is IMarketFacet, FacetBase {\n /// @notice Emitted when an admin supports a market\n event MarketListed(VToken indexed vToken);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account\n event DelegateUpdated(address indexed approver, address indexed delegate, bool approved);\n\n /// @notice Emitted when an admin unlists a market\n event MarketUnlisted(address indexed vToken);\n\n /// @notice Emitted when a market is initialized in a pool\n event PoolMarketInitialized(uint96 indexed poolId, address indexed market);\n\n /// @notice Emitted when a user enters or exits a pool (poolId = 0 means exit)\n event PoolSelected(address indexed account, uint96 previousPoolId, uint96 indexed newPoolId);\n\n /// @notice Emitted when a vToken market is removed from a pool\n event PoolMarketRemoved(uint96 indexed poolId, address indexed vToken);\n\n /// @notice Emitted when a new pool is created\n event PoolCreated(uint96 indexed poolId, string label);\n\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() public pure returns (bool) {\n return true;\n }\n\n /**\n * @notice Returns the vToken markets an account has entered in the Core Pool\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\n * @param account The address of the account to query\n * @return assets A dynamic array of vToken markets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n uint256 len;\n VToken[] memory _accountAssets = accountAssets[account];\n uint256 _accountAssetsLength = _accountAssets.length;\n\n VToken[] memory assetsIn = new VToken[](_accountAssetsLength);\n\n for (uint256 i; i < _accountAssetsLength; ++i) {\n Market storage market = getCorePoolMarket(address(_accountAssets[i]));\n if (market.isListed) {\n assetsIn[len] = _accountAssets[i];\n ++len;\n }\n }\n\n assembly {\n mstore(assetsIn, len)\n }\n\n return assetsIn;\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market\n * @return The list of market addresses\n */\n function getAllMarkets() external view returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\n address(this),\n vTokenBorrowed,\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param borrower Address of borrower whose collateral is being seized\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address borrower,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\n borrower,\n address(this),\n vTokenBorrowed,\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\n address(this),\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Returns whether the given account has entered the specified vToken market in the Core Pool\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the asset, otherwise false\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return getCorePoolMarket(address(vToken)).accountMembership[account];\n }\n\n /**\n * @notice Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\n * @param vToken The vToken Address of the market to check\n * @return listed True if the (Core Pool, vToken) market is listed, otherwise false\n */\n function isMarketListed(VToken vToken) external view returns (bool) {\n return getCorePoolMarket(address(vToken)).isListed;\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return Success indicator for whether each corresponding market was entered\n */\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\n }\n\n return results;\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @dev Only callable by the account itself or an approved delegate\n * @param onBehalf The address of the account entering the market\n * @param vToken The address of the vToken market to enable for the account\n * @return uint256 indicating the result (0 = success, non-zero = failure)\n * @custom:error NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\n */\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256) {\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\n revert NotAnApprovedDelegate();\n }\n return uint256(addToMarketInternal(VToken(vToken), onBehalf));\n }\n\n /**\n * @notice Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\n * @dev Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\n * @param market The address of the market (vToken) to unlist\n * @return uint256 0=success, otherwise a failure (See enum Error for details)\n */\n function unlistMarket(address market) external returns (uint256) {\n ensureAllowed(\"unlistMarket(address)\");\n\n Market storage _market = getCorePoolMarket(market);\n\n if (!_market.isListed) {\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.UNLIST_MARKET_NOT_LISTED);\n }\n\n require(actionPaused(market, Action.BORROW), \"borrow action is not paused\");\n require(actionPaused(market, Action.MINT), \"mint action is not paused\");\n require(actionPaused(market, Action.REDEEM), \"redeem action is not paused\");\n require(actionPaused(market, Action.REPAY), \"repay action is not paused\");\n require(actionPaused(market, Action.ENTER_MARKET), \"enter market action is not paused\");\n require(actionPaused(market, Action.LIQUIDATE), \"liquidate action is not paused\");\n require(actionPaused(market, Action.SEIZE), \"seize action is not paused\");\n require(actionPaused(market, Action.TRANSFER), \"transfer action is not paused\");\n require(actionPaused(market, Action.EXIT_MARKET), \"exit market action is not paused\");\n\n require(borrowCaps[market] == 0, \"borrow cap is not 0\");\n require(supplyCaps[market] == 0, \"supply cap is not 0\");\n\n require(_market.collateralFactorMantissa == 0, \"collateral factor is not 0\");\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow\n * @param vTokenAddress The address of the asset to be removed\n * @return Whether or not the account successfully exited the market\n */\n function exitMarket(address vTokenAddress) external returns (uint256) {\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\n require(oErr == 0, \"getAccountSnapshot failed\"); // semi-opaque error code\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\n if (allowed != 0) {\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\n }\n\n Market storage marketToExit = getCorePoolMarket(address(vToken));\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return uint256(Error.NO_ERROR);\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n uint256 i;\n for (; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n userAssetList[i] = userAssetList[len - 1];\n userAssetList.pop();\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(i < len);\n\n emit MarketExited(vToken, msg.sender);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _supportMarket to support the Isolated Lending Comptroller Interface\n * @param vToken The address of the market (token) to list\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function supportMarket(VToken vToken) external returns (uint256) {\n return __supportMarket(vToken);\n }\n\n /**\n * @notice Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\n * @dev Allows a privileged role to add and list markets to the Comptroller\n * @param vToken The address of the vToken market to list in the Core Pool\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _supportMarket(VToken vToken) external returns (uint256) {\n return __supportMarket(vToken);\n }\n\n /**\n * @notice Grants or revokes the borrowing or redeeming delegate rights to / from an account\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\n * will see the debt on their account\n * Upon a delegated redeem, the delegate will receive the redeemed amount and the approver\n * will see a deduction in his vToken balance\n * @param delegate The address to update the rights for\n * @param approved Whether to grant (true) or revoke (false) the borrowing or redeeming rights\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n require(approvedDelegates[msg.sender][delegate] != approved, \"Delegation status unchanged\");\n\n _updateDelegate(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Allows a user to switch to a new pool (e.g., e-mode ).\n * @param poolId The ID of the pool the user wants to enter.\n * @custom:error PoolDoesNotExist The specified pool ID does not exist.\n * @custom:error AlreadyInSelectedPool The user is already in the target pool.\n * @custom:error IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.\n * @custom:error LiquidityCheckFailed The user's liquidity is insufficient after switching pools.\n * @custom:error InactivePool The user is trying to enter inactive pool.\n * @custom:event PoolSelected Emitted after a successful pool switch.\n */\n function enterPool(uint96 poolId) external {\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n\n if (poolId == userPoolId[msg.sender]) {\n revert AlreadyInSelectedPool();\n }\n\n if (poolId != corePoolId && !pools[poolId].isActive) {\n revert InactivePool(poolId);\n }\n\n if (!hasValidPoolBorrows(msg.sender, poolId)) {\n revert IncompatibleBorrowedAssets();\n }\n\n emit PoolSelected(msg.sender, userPoolId[msg.sender], poolId);\n\n userPoolId[msg.sender] = poolId;\n\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n msg.sender,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n if (err != Error.NO_ERROR || shortfall > 0) {\n revert LiquidityCheckFailed(uint256(err), shortfall);\n }\n }\n\n /**\n * @notice Creates a new pool with the given label.\n * @param label name for the pool (must be non-empty).\n * @return poolId The incremental unique identifier of the newly created pool.\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string.\n * @custom:event PoolCreated Emitted after successfully creating a new pool.\n */\n function createPool(string memory label) external returns (uint96) {\n ensureAllowed(\"createPool(string)\");\n\n if (bytes(label).length == 0) {\n revert EmptyPoolLabel();\n }\n\n uint96 poolId = ++lastPoolId;\n PoolData storage newPool = pools[poolId];\n newPool.label = label;\n newPool.isActive = true;\n\n emit PoolCreated(poolId, label);\n return poolId;\n }\n\n /**\n * @notice Batch initializes market entries with basic config.\n * @param poolIds Array of pool IDs.\n * @param vTokens Array of market (vToken) addresses.\n * @custom:error ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\n * @custom:error MarketNotListedInCorePool Reverts if the market is not listed in the core pool.\n * @custom:error MarketAlreadyListed Reverts if the given market is already listed in the specified pool.\n * @custom:error InactivePool Reverts if attempted to add markets to an inactive pool.\n * @custom:event PoolMarketInitialized Emitted after successfully initializing a market in a pool.\n */\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external {\n ensureAllowed(\"addPoolMarkets(uint96[],address[])\");\n\n uint256 len = poolIds.length;\n if (len == 0 || len != vTokens.length) {\n revert ArrayLengthMismatch();\n }\n\n for (uint256 i; i < len; i++) {\n _addPoolMarket(poolIds[i], vTokens[i]);\n }\n }\n\n /**\n * @notice Removes a market (vToken) from the specified pool.\n * @param poolId The ID of the pool from which the market should be removed.\n * @param vToken The address of the market token to remove.\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\n * @custom:error PoolMarketNotFound Reverts if the market is not listed in the pool.\n * @custom:event PoolMarketRemoved Emitted after a market is successfully removed from a pool.\n */\n function removePoolMarket(uint96 poolId, address vToken) external {\n ensureAllowed(\"removePoolMarket(uint96,address)\");\n\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\n if (!_poolMarkets[index].isListed) {\n revert PoolMarketNotFound(poolId, vToken);\n }\n\n address[] storage assets = pools[poolId].vTokens;\n\n uint256 length = assets.length;\n for (uint256 i; i < length; i++) {\n if (assets[i] == vToken) {\n assets[i] = assets[length - 1];\n assets.pop();\n break;\n }\n }\n\n delete _poolMarkets[index];\n\n emit PoolMarketRemoved(poolId, vToken);\n }\n\n /**\n * @notice Get the core pool collateral factor for a vToken\n * @param vToken The address of the vToken to get the collateral factor for\n * @return The collateral factor for the vToken, scaled by 1e18\n */\n function getCollateralFactor(address vToken) external view returns (uint256) {\n (uint256 cf, , ) = getLiquidationParams(corePoolId, vToken);\n return cf;\n }\n\n /**\n * @notice Get the core pool liquidation threshold for a vToken\n * @param vToken The address of the vToken to get the liquidation threshold for\n * @return The liquidation threshold for the vToken, scaled by 1e18\n */\n function getLiquidationThreshold(address vToken) external view returns (uint256) {\n (, uint256 lt, ) = getLiquidationParams(corePoolId, vToken);\n return lt;\n }\n\n /**\n * @notice Get the core pool liquidation Incentive for a vToken\n * @param vToken The address of the vToken to get the liquidation Incentive for\n * @return liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\n */\n function getLiquidationIncentive(address vToken) external view returns (uint256) {\n (, , uint256 li) = getLiquidationParams(corePoolId, vToken);\n return li;\n }\n\n /**\n * @notice Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\n * @dev The value is determined by the pool entered by the account and the specified vToken via\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used.\n * This value is used for account liquidity calculations and liquidation checks.\n * @param account The account whose pool is used to determine the market's risk parameters.\n * @param vToken The address of the vToken market.\n * @param weightingStrategy The weighting strategy to use:\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\n * @return factor The effective loan-to-value factor, scaled by 1e18.\n */\n function getEffectiveLtvFactor(\n address account,\n address vToken,\n WeightFunction weightingStrategy\n ) external view returns (uint256) {\n (uint256 cf, uint256 lt, ) = getLiquidationParams(userPoolId[account], vToken);\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) return cf;\n else if (weightingStrategy == WeightFunction.USE_LIQUIDATION_THRESHOLD) return lt;\n else revert InvalidWeightingStrategy(weightingStrategy);\n }\n\n /**\n * @notice Get the Effective Liquidation Incentive for a given account and market\n * @dev The incentive is determined by the pool entered by the account and the specified vToken via\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\n * @param account The account whose pool is used to determine the market's risk parameters\n * @param vToken The address of the vToken market\n * @return The liquidation Incentive for the vToken, scaled by 1e18\n */\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256) {\n (, , uint256 li) = getLiquidationParams(userPoolId[account], vToken);\n return li;\n }\n\n /**\n * @notice Returns the full list of vTokens for a given pool ID.\n * @param poolId The ID of the pool whose vTokens are being queried.\n * @return An array of vToken addresses associated with the pool.\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\n */\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory) {\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n return pools[poolId].vTokens;\n }\n\n /**\n * @notice Returns the market configuration for a vToken in the core pool (poolId = 0).\n * @dev Fetches the Market struct associated with the core pool and returns all relevant parameters.\n * @param vToken The address of the vToken whose market configuration is to be fetched.\n * @return isListed Whether the market is listed and enabled.\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\n * @return isVenus Whether this market is eligible for VENUS rewards.\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\n * @return liquidationIncentiveMantissa The max liquidation incentive allowed for this market, in mantissa.\n * @return marketPoolId The pool ID this market belongs to.\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\n */\n function markets(\n address vToken\n )\n external\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n )\n {\n return poolMarkets(corePoolId, vToken);\n }\n\n /**\n * @notice Returns the market configuration for a vToken from _poolMarkets.\n * @dev Fetches the Market struct associated with the poolId and returns all relevant parameters.\n * @param poolId The ID of the pool whose market configuration is being queried.\n * @param vToken The address of the vToken whose market configuration is to be fetched.\n * @return isListed Whether the market is listed and enabled.\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\n * @return isVenus Whether this market is eligible for XVS rewards.\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\n * @return marketPoolId The pool ID this market belongs to.\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\n */\n function poolMarkets(\n uint96 poolId,\n address vToken\n )\n public\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n )\n {\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n PoolMarketId key = getPoolMarketIndex(poolId, vToken);\n Market storage m = _poolMarkets[key];\n\n return (\n m.isListed,\n m.collateralFactorMantissa,\n m.isVenus,\n m.liquidationThresholdMantissa,\n m.liquidationIncentiveMantissa,\n m.poolId,\n m.isBorrowAllowed\n );\n }\n\n /**\n * @notice Returns true if the user can switch to the given target pool, i.e.,\n * all markets they have borrowed from are also borrowable in the target pool.\n * @param account The address of the user attempting to switch pools.\n * @param targetPoolId The pool ID the user wants to switch into.\n * @return bool True if the switch is allowed, otherwise False.\n */\n function hasValidPoolBorrows(address account, uint96 targetPoolId) public view returns (bool) {\n VToken[] memory assets = accountAssets[account];\n if (targetPoolId != corePoolId && mintedVAIs[account] > 0) {\n return false;\n }\n\n for (uint256 i; i < assets.length; i++) {\n VToken vToken = assets[i];\n PoolMarketId index = getPoolMarketIndex(targetPoolId, address(vToken));\n\n if (!_poolMarkets[index].isBorrowAllowed) {\n if (vToken.borrowBalanceStored(account) > 0) {\n return false;\n }\n }\n }\n return true;\n }\n\n function _updateDelegate(address approver, address delegate, bool approved) internal {\n approvedDelegates[approver][delegate] = approved;\n emit DelegateUpdated(approver, delegate, approved);\n }\n\n function _addMarketInternal(VToken vToken) internal {\n uint256 allMarketsLength = allMarkets.length;\n for (uint256 i; i < allMarketsLength; ++i) {\n require(allMarkets[i] != vToken, \"already added\");\n }\n allMarkets.push(vToken);\n }\n\n function _initializeMarket(address vToken) internal {\n uint32 blockNumber = getBlockNumberAsUint32();\n\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = venusInitialIndex;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = venusInitialIndex;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n function __supportMarket(VToken vToken) internal returns (uint256) {\n ensureAllowed(\"_supportMarket(address)\");\n\n if (getCorePoolMarket(address(vToken)).isListed) {\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\n }\n\n vToken.isVToken(); // Sanity check to make sure its really a VToken\n\n // Note that isVenus is not in active use anymore\n Market storage newMarket = getCorePoolMarket(address(vToken));\n newMarket.isListed = true;\n newMarket.isVenus = false;\n newMarket.collateralFactorMantissa = 0;\n\n _addMarketInternal(vToken);\n _initializeMarket(address(vToken));\n\n emit MarketListed(vToken);\n\n return uint256(Error.NO_ERROR);\n }\n\n function _addPoolMarket(uint96 poolId, address vToken) internal {\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (!pools[poolId].isActive) revert InactivePool(poolId);\n\n // Core Pool Index\n PoolMarketId index = getPoolMarketIndex(corePoolId, vToken);\n if (!_poolMarkets[index].isListed) revert MarketNotListedInCorePool();\n\n // Pool Index\n index = getPoolMarketIndex(poolId, vToken);\n if (_poolMarkets[index].isListed) revert MarketAlreadyListed(poolId, vToken);\n\n Market storage m = _poolMarkets[index];\n m.poolId = poolId;\n m.isListed = true;\n\n pools[poolId].vTokens.push(vToken);\n\n emit PoolMarketInitialized(poolId, vToken);\n }\n\n /**\n * @notice Returns only the core risk parameters (CF, LI, LT) for a vToken in a specific pool.\n * @dev If the pool is inactive, or if the vToken is not configured in the given pool and\n * `allowCorePoolFallback` is enabled, falls back to the core pool (poolId = 0) values.\n * @return collateralFactorMantissa The max borrowable percentage of collateral, in mantissa.\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\n */\n function getLiquidationParams(\n uint96 poolId,\n address vToken\n )\n internal\n view\n returns (\n uint256 collateralFactorMantissa,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa\n )\n {\n PoolData storage pool = pools[poolId];\n Market storage market;\n\n if (poolId == corePoolId || !pool.isActive) {\n market = getCorePoolMarket(vToken);\n } else {\n PoolMarketId poolKey = getPoolMarketIndex(poolId, vToken);\n Market storage poolMarket = _poolMarkets[poolKey];\n market = (!poolMarket.isListed && pool.allowCorePoolFallback) ? getCorePoolMarket(vToken) : poolMarket;\n }\n\n return (\n market.collateralFactorMantissa,\n market.liquidationThresholdMantissa,\n market.liquidationIncentiveMantissa\n );\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/PolicyFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { IPolicyFacet } from \"../interfaces/IPolicyFacet.sol\";\n\nimport { XVSRewardsHelper } from \"./XVSRewardsHelper.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\nimport { WeightFunction } from \"../interfaces/IFacetBase.sol\";\n\n/**\n * @title PolicyFacet\n * @author Venus\n * @dev This facet contains all the hooks used while transferring the assets\n * @notice This facet contract contains all the external pre-hook functions related to vToken\n */\ncontract PolicyFacet is IPolicyFacet, XVSRewardsHelper {\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.MINT);\n ensureListed(getCorePoolMarket(vToken));\n\n uint256 supplyCap = supplyCaps[vToken];\n require(supplyCap != 0, \"market supply cap is 0\");\n\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n require(nextTotalSupply <= supplyCap, \"market supply cap reached\");\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, minter);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being minted\n * @param minter The address minting the tokens\n * @param actualMintAmount The amount of the underlying asset being minted\n * @param mintTokens The number of tokens being minted\n */\n // solhint-disable-next-line no-unused-vars\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(minter, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REDEEM);\n\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, redeemer);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being redeemed\n * @param redeemer The address redeeming the tokens\n * @param redeemAmount The amount of the underlying asset being redeemed\n * @param redeemTokens The number of tokens being redeemed\n */\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\n require(redeemTokens != 0 || redeemAmount == 0, \"redeemTokens zero\");\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.BORROW);\n ensureListed(getCorePoolMarket(vToken));\n poolBorrowAllowed(borrower, vToken);\n\n uint256 borrowCap = borrowCaps[vToken];\n require(borrowCap != 0, \"market borrow cap is 0\");\n\n if (!getCorePoolMarket(vToken).accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n require(msg.sender == vToken, \"sender must be vToken\");\n\n // attempt to add borrower to the market\n Error err = addToMarketInternal(VToken(vToken), borrower);\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n }\n\n (uint256 collateralPrice, uint256 debtPrice) = deviationBoundedOracle.getBoundedPricesView(vToken);\n if (collateralPrice == 0 || debtPrice == 0) {\n return uint256(Error.PRICE_ERROR);\n }\n\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\n require(nextTotalBorrows <= borrowCap, \"market borrow cap reached\");\n\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset whose underlying is being borrowed\n * @param borrower The address borrowing the underlying\n * @param borrowAmount The amount of the underlying asset requested to borrow\n */\n // solhint-disable-next-line no-unused-vars\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param payer The account which would repay the asset\n * @param borrower The account which borrowed the asset\n * @param repayAmount The amount of the underlying asset the account would repay\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function repayBorrowAllowed(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 repayAmount // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REPAY);\n ensureListed(getCorePoolMarket(vToken));\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being repaid\n * @param payer The address repaying the borrow\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n */\n function repayBorrowVerify(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n */\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256) {\n checkProtocolPauseState();\n\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\n return uint256(Error.UNAUTHORIZED);\n }\n\n ensureListed(getCorePoolMarket(vTokenCollateral));\n uint256 borrowBalance;\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(getCorePoolMarket(vTokenBorrowed));\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n } else {\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\n }\n\n if (isForcedLiquidationEnabled[vTokenBorrowed] || isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n return uint(Error.TOO_MUCH_REPAY);\n }\n return uint(Error.NO_ERROR);\n }\n\n /* The borrower must have shortfall in order to be liquidatable */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\n borrower,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_LIQUIDATION_THRESHOLD\n );\n\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall == 0) {\n return uint256(Error.INSUFFICIENT_SHORTFALL);\n }\n\n // The liquidator may not repay more than what is allowed by the closeFactor\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\n return uint256(Error.TOO_MUCH_REPAY);\n }\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n * @param seizeTokens The amount of collateral token that will be seized\n */\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = getCorePoolMarket(vTokenCollateral);\n\n // We've added VAIController as a borrowed token list check for seize\n ensureListed(market);\n\n if (!market.accountMembership[borrower]) {\n return uint256(Error.MARKET_NOT_COLLATERAL);\n }\n\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(getCorePoolMarket(vTokenBorrowed));\n }\n\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\n return uint256(Error.COMPTROLLER_MISMATCH);\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vTokenCollateral);\n distributeSupplierVenus(vTokenCollateral, borrower);\n distributeSupplierVenus(vTokenCollateral, liquidator);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, src);\n distributeSupplierVenus(vToken, dst);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being transferred\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n */\n // solhint-disable-next-line no-unused-vars\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(src, vToken);\n prime.accrueInterestAndUpdateScore(dst, vToken);\n }\n }\n\n /**\n * @notice Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\n * @param account The account get liquidity for\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n * account shortfall below collateral requirements)\n */\n function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\n account,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity wrt liquidation threshold requirements\n * @param account The account get liquidity for\n * @return (possible error code (semi-opaque),\n account liquidity in excess of liquidation threshold requirements,\n * account shortfall below liquidation threshold requirements)\n */\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\n account,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_LIQUIDATION_THRESHOLD\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return (possible error code (semi-opaque),\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n // setter functionality\n /**\n * @notice Set XVS speed for a single market\n * @dev Allows the contract admin to set XVS speed for a market\n * @param vTokens The market whose XVS speed to update\n * @param supplySpeeds New XVS speed for supply\n * @param borrowSpeeds New XVS speed for borrow\n */\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external {\n ensureAdmin();\n\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid input\");\n\n for (uint256 i; i < numTokens; ++i) {\n ensureNonzeroAddress(address(vTokens[i]));\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @dev Internal function to set XVS speed for a single market\n * @param vToken The market whose XVS speed to update\n * @param supplySpeed New XVS speed for supply\n * @param borrowSpeed New XVS speed for borrow\n * @custom:event VenusSupplySpeedUpdated Emitted after the venus supply speed for a market is updated\n * @custom:event VenusBorrowSpeedUpdated Emitted after the venus borrow speed for a market is updated\n */\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n ensureListed(getCorePoolMarket(address(vToken)));\n\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n\n updateVenusSupplyIndex(address(vToken));\n // Update speed and emit event\n venusSupplySpeeds[address(vToken)] = supplySpeed;\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @dev Checks if vToken borrowing is allowed in the account's entered pool\n * Reverts if borrowing is not permitted\n * @param account The address of the account whose borrow permission is being checked\n * @param vToken The vToken market to check borrowing status for\n * @custom:error BorrowNotAllowedInPool Reverts if borrowing is not allowed in the account's entered pool\n * @custom:error InactivePool Reverts if borrowing in an inactive pool.\n */\n function poolBorrowAllowed(address account, address vToken) internal view {\n uint96 userPool = userPoolId[account];\n PoolMarketId index = getPoolMarketIndex(userPool, vToken);\n if (!_poolMarkets[index].isBorrowAllowed) {\n revert BorrowNotAllowedInPool();\n }\n if (userPool != corePoolId && !pools[userPool].isActive) {\n revert InactivePool(userPool);\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/RewardFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { IRewardFacet } from \"../interfaces/IRewardFacet.sol\";\nimport { XVSRewardsHelper } from \"./XVSRewardsHelper.sol\";\nimport { VBep20Interface } from \"../../../Tokens/VTokens/VTokenInterfaces.sol\";\nimport { WeightFunction } from \"../interfaces/IFacetBase.sol\";\n\n/**\n * @title RewardFacet\n * @author Venus\n * @dev This facet contains all the methods related to the reward functionality\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\n */\ncontract RewardFacet is IRewardFacet, XVSRewardsHelper {\n /// @notice Emitted when Venus is granted by admin\n event VenusGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when XVS are seized for the holder\n event VenusSeized(address indexed holder, uint256 amount);\n\n using SafeERC20 for IERC20;\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets and VAI\n * @param holder The address to claim XVS for\n */\n function claimVenus(address holder) public {\n return claimVenus(holder, allMarkets);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in the specified markets\n * @param holder The address to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n */\n function claimVenus(address holder, VToken[] memory vTokens) public {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, vTokens, true, true);\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\n claimVenus(holders, vTokens, borrowers, suppliers, false);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\n * @param holder The address to claim XVS for\n */\n function claimVenusAsCollateral(address holder) external {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, allMarkets, true, true, true);\n }\n\n /**\n * @notice Transfer XVS to the user with user's shortfall considered\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\n * @param user The address of the user to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n * @param shortfall The shortfall of the user\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\n * @return The amount of XVS which was NOT transferred to the user\n */\n function grantXVSInternal(\n address user,\n uint256 amount,\n uint256 shortfall,\n bool collateral\n ) internal returns (uint256) {\n // If the user is blacklisted, they can't get XVS rewards\n require(\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\n \"Blacklisted\"\n );\n\n IERC20 xvs_ = IERC20(xvs);\n\n if (amount == 0 || amount > xvs_.balanceOf(address(this))) {\n return amount;\n }\n\n if (shortfall == 0) {\n xvs_.safeTransfer(user, amount);\n return 0;\n }\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\n // anything, otherwise, we will transfer the pending xvs as collateral to\n // vXVS token and mint vXVS for the user\n //\n // If mintBehalf failed, don't grant any xvs\n require(collateral, \"bankrupt\");\n\n address xvsVToken_ = xvsVToken;\n\n xvs_.safeApprove(xvsVToken_, 0);\n xvs_.safeApprove(xvsVToken_, amount);\n require(VBep20Interface(xvsVToken_).mintBehalf(user, amount) == uint256(Error.NO_ERROR), \"mint behalf error\");\n\n // set venusAccrued[user] to 0\n return 0;\n }\n\n /*** Venus Distribution Admin ***/\n\n /**\n * @notice Transfer XVS to the recipient\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\n * Note: If there is not enough XVS, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n */\n function _grantXVS(address recipient, uint256 amount) external {\n ensureAdmin();\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\n require(amountLeft == 0, \"no xvs\");\n emit VenusGranted(recipient, amount);\n }\n\n /**\n * @dev Seize XVS tokens from the specified holders and transfer to recipient\n * @notice Seize XVS rewards allocated to holders\n * @param holders Addresses of the XVS holders\n * @param recipient Address of the XVS token recipient\n * @return The total amount of XVS tokens seized and transferred to recipient\n */\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256) {\n ensureAllowed(\"seizeVenus(address[],address)\");\n\n uint256 holdersLength = holders.length;\n uint256 totalHoldings;\n\n updateAndDistributeRewardsInternal(holders, allMarkets, true, true);\n for (uint256 j; j < holdersLength; ++j) {\n address holder = holders[j];\n uint256 userHolding = venusAccrued[holder];\n\n if (userHolding != 0) {\n totalHoldings += userHolding;\n delete venusAccrued[holder];\n }\n\n emit VenusSeized(holder, userHolding);\n }\n\n if (totalHoldings != 0) {\n IERC20(xvs).safeTransfer(recipient, totalHoldings);\n emit VenusGranted(recipient, totalHoldings);\n }\n\n return totalHoldings;\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @dev The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices.\n * When DBO protection mode is active, a holder with a position that is healthy at spot prices may still\n * show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when\n * `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO.\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\n */\n function claimVenus(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) public {\n uint256 holdersLength = holders.length;\n\n updateAndDistributeRewardsInternal(holders, vTokens, borrowers, suppliers);\n for (uint256 j; j < holdersLength; ++j) {\n address holder = holders[j];\n\n // If there is a positive shortfall, the XVS reward is accrued,\n // but won't be granted to this holder\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n holder,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n\n uint256 value = venusAccrued[holder];\n delete venusAccrued[holder];\n\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\n\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\n if (returnAmount != 0) {\n venusAccrued[holder] = returnAmount;\n }\n }\n }\n\n /**\n * @notice Update and distribute tokens\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function updateAndDistributeRewardsInternal(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers\n ) internal {\n uint256 j;\n uint256 holdersLength = holders.length;\n uint256 vTokensLength = vTokens.length;\n\n for (uint256 i; i < vTokensLength; ++i) {\n VToken vToken = vTokens[i];\n ensureListed(getCorePoolMarket(address(vToken)));\n if (borrowers) {\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n for (j = 0; j < holdersLength; ++j) {\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\n }\n }\n\n if (suppliers) {\n updateVenusSupplyIndex(address(vToken));\n for (j = 0; j < holdersLength; ++j) {\n distributeSupplierVenus(address(vToken), holders[j]);\n }\n }\n }\n }\n\n /**\n * @notice Returns the XVS vToken address\n * @return The address of XVS vToken\n */\n function getXVSVTokenAddress() external view returns (address) {\n return xvsVToken;\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/SetterFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { ComptrollerLensInterface } from \"../../ComptrollerLensInterface.sol\";\nimport { VAIControllerInterface } from \"../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { IPrime } from \"../../../Tokens/Prime/IPrime.sol\";\nimport { ISetterFacet } from \"../interfaces/ISetterFacet.sol\";\nimport { FacetBase } from \"./FacetBase.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\n\n/**\n * @title SetterFacet\n * @author Venus\n * @dev This facet contains all the setters for the states\n * @notice This facet contract contains all the configurational setter functions\n */\ncontract SetterFacet is ISetterFacet, FacetBase {\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor for a market in a pool is changed by admin\n event NewCollateralFactor(\n uint96 indexed poolId,\n VToken indexed vToken,\n uint256 oldCollateralFactorMantissa,\n uint256 newCollateralFactorMantissa\n );\n\n /// @notice Emitted when liquidation incentive for a market in a pool is changed by admin\n event NewLiquidationIncentive(\n uint96 indexed poolId,\n address indexed vToken,\n uint256 oldLiquidationIncentiveMantissa,\n uint256 newLiquidationIncentiveMantissa\n );\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\n\n /// @notice Emitted when deviation bounded oracle is changed\n event NewDeviationBoundedOracle(\n IDeviationBoundedOracle oldDeviationBoundedOracle,\n IDeviationBoundedOracle newDeviationBoundedOracle\n );\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when VAIController is changed\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\n\n /// @notice Emitted when VAI mint rate is changed by admin\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\n\n /// @notice Emitted when protocol state is changed by admin\n event ActionProtocolPaused(bool state);\n\n /// @notice Emitted when treasury guardian is changed\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\n\n /// @notice Emitted when treasury address is changed\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\n\n /// @notice Emitted when treasury percent is changed\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\n\n /// @notice Emitted when liquidator adress is changed\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\n\n /// @notice Emitted when ComptrollerLens address is changed\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\n\n /// @notice Emitted when pause guardian is changed\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\n\n /// @notice Emitted when VAI Vault info is changed\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\n\n /// @notice Emitted when Venus VAI Vault rate is changed\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\n\n /// @notice Emitted when prime token contract address is changed\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for all users in a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\n event IsForcedLiquidationEnabledForUserUpdated(address indexed borrower, address indexed vToken, bool enable);\n\n /// @notice Emitted when XVS token address is changed\n event NewXVSToken(address indexed oldXVS, address indexed newXVS);\n\n /// @notice Emitted when XVS vToken address is changed\n event NewXVSVToken(address indexed oldXVSVToken, address indexed newXVSVToken);\n\n /// @notice Emitted when an account's flash loan whitelist status is updated\n event IsAccountFlashLoanWhitelisted(address indexed account, bool indexed isWhitelisted);\n\n /// @notice Emitted when liquidation threshold for a market in a pool is changed by admin\n event NewLiquidationThreshold(\n uint96 indexed poolId,\n VToken indexed vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\n );\n\n /// @notice Emitted when the borrowAllowed flag is updated for a market\n event BorrowAllowedUpdated(uint96 indexed poolId, address indexed market, bool oldStatus, bool newStatus);\n\n /// @notice Emitted when pool active status updated\n event PoolActiveStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\n\n /// @notice Emitted when pool label is updated\n event PoolLabelUpdated(uint96 indexed poolId, string oldLabel, string newLabel);\n\n /// @notice Emitted when pool Fallback status is updated\n event PoolFallbackStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\n\n /// @notice Emitted when flash loan pause status changes\n event FlashLoanPauseChanged(bool oldPaused, bool newPaused);\n\n /**\n * @notice Compare two addresses to ensure they are different\n * @param oldAddress The original address to compare\n * @param newAddress The new address to compare\n */\n modifier compareAddress(address oldAddress, address newAddress) {\n require(oldAddress != newAddress, \"old address is same as new address\");\n _;\n }\n\n /**\n * @notice Compare two values to ensure they are different\n * @param oldValue The original value to compare\n * @param newValue The new value to compare\n */\n modifier compareValue(uint256 oldValue, uint256 newValue) {\n require(oldValue != newValue, \"old value is same as new value\");\n _;\n }\n\n /**\n * @notice Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\n * @param newOracle The new price oracle to set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\n return __setPriceOracle(newOracle);\n }\n\n /**\n * @notice Sets a new price oracle for the comptroller\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\n * @param newOracle The new price oracle to set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\n return __setPriceOracle(newOracle);\n }\n\n /**\n * @notice Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\n return __setCloseFactor(newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the closeFactor used when liquidating borrows\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\n return __setCloseFactor(newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Allows the contract admin to set the address of access control of this contract\n * @param newAccessControlAddress New address for the access control\n * @return uint256 0=success, otherwise will revert\n */\n function _setAccessControl(\n address newAccessControlAddress\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newAccessControlAddress);\n\n address oldAccessControlAddress = accessControl;\n\n accessControl = newAccessControlAddress;\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256) {\n ensureAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n return __setCollateralFactor(corePoolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\n }\n\n /**\n * @notice Sets the liquidation incentive for a market in the Core Pool only.\n * @param vToken The market to set the liquidationIncentive for\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setLiquidationIncentive(\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n ) external returns (uint256) {\n ensureAllowed(\"setLiquidationIncentive(address,uint256)\");\n return __setLiquidationIncentive(corePoolId, vToken, newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Sets the collateral factor and liquidation threshold for a market in the specified pool.\n * @param poolId The ID of the pool.\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setCollateralFactor(\n uint96 poolId,\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256) {\n ensureAllowed(\"setCollateralFactor(uint96,address,uint256,uint256)\");\n return __setCollateralFactor(poolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\n }\n\n /**\n * @notice Sets the liquidation incentive for a market in the specified pool.\n * @param poolId The ID of the pool.\n * @param vToken The market to set the liquidationIncentive for\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setLiquidationIncentive(\n uint96 poolId,\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n ) external returns (uint256) {\n ensureAllowed(\"setLiquidationIncentive(uint96,address,uint256)\");\n return __setLiquidationIncentive(poolId, vToken, newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Update the address of the liquidator contract\n * @dev Allows the contract admin to update the address of liquidator contract\n * @param newLiquidatorContract_ The new address of the liquidator contract\n */\n function _setLiquidatorContract(\n address newLiquidatorContract_\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newLiquidatorContract_);\n address oldLiquidatorContract = liquidatorContract;\n liquidatorContract = newLiquidatorContract_;\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\n }\n\n /**\n * @notice Admin function to change the Pause Guardian\n * @dev Allows the contract admin to change the Pause Guardian\n * @param newPauseGuardian The address of the new Pause Guardian\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _setPauseGuardian(\n address newPauseGuardian\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(newPauseGuardian);\n\n // Save current value for inclusion in log\n address oldPauseGuardian = pauseGuardian;\n // Store pauseGuardian with value newPauseGuardian\n pauseGuardian = newPauseGuardian;\n\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\n */\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\n }\n\n /**\n * @notice Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\n }\n\n /**\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\n }\n\n /**\n * @notice Set whole protocol pause/unpause state\n * @dev Allows a privileged role to pause/unpause protocol\n * @param state The new state (true=paused, false=unpaused)\n * @return bool The updated state of the protocol\n */\n function _setProtocolPaused(bool state) external returns (bool) {\n ensureAllowed(\"_setProtocolPaused(bool)\");\n\n protocolPaused = state;\n emit ActionProtocolPaused(state);\n return state;\n }\n\n /**\n * @notice Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n __setActionsPaused(markets_, actions_, paused_);\n }\n\n /**\n * @notice Pause/unpause certain actions\n * @dev Allows a privileged role to pause/unpause the protocol action state\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n __setActionsPaused(markets_, actions_, paused_);\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function setActionPausedInternal(address market, Action action, bool paused) internal {\n ensureListed(getCorePoolMarket(market));\n _actionPaused[market][uint256(action)] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @notice Sets a new VAI controller\n * @dev Admin function to set a new VAI controller\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIController(\n VAIControllerInterface vaiController_\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(vaiController_));\n\n VAIControllerInterface oldVaiController = vaiController;\n vaiController = vaiController_;\n emit NewVAIController(oldVaiController, vaiController_);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the VAI mint rate\n * @param newVAIMintRate The new VAI mint rate to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIMintRate(\n uint256 newVAIMintRate\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n uint256 oldVAIMintRate = vaiMintRate;\n vaiMintRate = newVAIMintRate;\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the minted VAI amount of the `owner`\n * @param owner The address of the account to set\n * @param amount The amount of VAI to set to the account\n * @return The number of minted VAI by `owner`\n */\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\n checkProtocolPauseState();\n\n // Pausing is a very serious situation - we revert to sound the alarms\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \"VAI is paused\");\n // Check caller is vaiController\n if (msg.sender != address(vaiController)) {\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\n }\n mintedVAIs[owner] = amount;\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the treasury data.\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\n * @param newTreasuryAddress The new address of the treasury to be set\n * @param newTreasuryPercent The new treasury percent to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256) {\n // Check caller is admin\n ensureAdminOr(treasuryGuardian);\n\n require(newTreasuryPercent < 1e18, \"percent >= 100%\");\n ensureNonzeroAddress(newTreasuryGuardian);\n ensureNonzeroAddress(newTreasuryAddress);\n\n address oldTreasuryGuardian = treasuryGuardian;\n address oldTreasuryAddress = treasuryAddress;\n uint256 oldTreasuryPercent = treasuryPercent;\n\n treasuryGuardian = newTreasuryGuardian;\n treasuryAddress = newTreasuryAddress;\n treasuryPercent = newTreasuryPercent;\n\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\n\n return uint256(Error.NO_ERROR);\n }\n\n /*** Venus Distribution ***/\n\n /**\n * @dev Set ComptrollerLens contract address\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptrollerLens(\n ComptrollerLensInterface comptrollerLens_\n ) external virtual compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the amount of XVS distributed per block to VAI Vault\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\n */\n function _setVenusVAIVaultRate(\n uint256 venusVAIVaultRate_\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\n ensureAdmin();\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\n venusVAIVaultRate = venusVAIVaultRate_;\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\n }\n\n /**\n * @notice Set the VAI Vault infos\n * @param vault_ The address of the VAI Vault\n * @param releaseStartBlock_ The start block of release to VAI Vault\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\n */\n function _setVAIVaultInfo(\n address vault_,\n uint256 releaseStartBlock_,\n uint256 minReleaseAmount_\n ) external compareAddress(vaiVaultAddress, vault_) {\n ensureAdmin();\n ensureNonzeroAddress(vault_);\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n\n vaiVaultAddress = vault_;\n releaseStartBlock = releaseStartBlock_;\n minReleaseAmount = minReleaseAmount_;\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\n }\n\n /**\n * @notice Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\n * @param _prime The new prime token contract to be set\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function setPrimeToken(IPrime _prime) external returns (uint256) {\n return __setPrimeToken(_prime);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime The new prime token contract to be set\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPrimeToken(IPrime _prime) external returns (uint256) {\n return __setPrimeToken(_prime);\n }\n\n /**\n * @notice Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n __setForcedLiquidation(vTokenBorrowed, enable);\n }\n\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\n * borrows in the market may be liquidated regardless of the account liquidity\n * @dev Allows a privileged role to set enable/disable forced liquidations\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n __setForcedLiquidation(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Enables forced liquidations for user's borrows in a certain market. If forced\n * liquidation is enabled, user's borrows in the market may be liquidated regardless of\n * the account liquidity. Forced liquidation may be enabled for a user even if it is not\n * enabled for the entire market.\n * @param borrower The address of the borrower\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external {\n ensureAllowed(\"_setForcedLiquidationForUser(address,address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(getCorePoolMarket(vTokenBorrowed));\n }\n isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledForUserUpdated(borrower, vTokenBorrowed, enable);\n }\n\n /**\n * @notice Set the address of the XVS token\n * @param xvs_ The address of the XVS token\n */\n function _setXVSToken(address xvs_) external {\n ensureAdmin();\n ensureNonzeroAddress(xvs_);\n\n emit NewXVSToken(xvs, xvs_);\n xvs = xvs_;\n }\n\n /**\n * @notice Set the address of the XVS vToken\n * @param xvsVToken_ The address of the XVS vToken\n */\n function _setXVSVToken(address xvsVToken_) external {\n ensureAdmin();\n ensureNonzeroAddress(xvsVToken_);\n\n address underlying = VToken(xvsVToken_).underlying();\n require(underlying == xvs, \"invalid xvs vtoken address\");\n\n emit NewXVSVToken(xvsVToken, xvsVToken_);\n xvsVToken = xvsVToken_;\n }\n\n /**\n * @notice Adds/Removes an account to the flash loan whitelist\n * @param account The account to authorize for flash loans\n * @param isWhiteListed True to whitelist the account for flash loans, false to remove from whitelist\n * @custom:event Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\n */\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external {\n ensureAllowed(\"setWhiteListFlashLoanAccount(address,bool)\");\n ensureNonzeroAddress(account);\n\n // If the account's status is already the same as the desired status, do nothing\n if (authorizedFlashLoan[account] == isWhiteListed) {\n return;\n }\n\n authorizedFlashLoan[account] = isWhiteListed;\n emit IsAccountFlashLoanWhitelisted(account, isWhiteListed);\n }\n\n /**\n * @notice Pause or unpause flash loans system-wide\n * @param paused True to pause flash loans, false to unpause\n * @custom:access Only Governance\n * @custom:event Emits FlashLoanPauseChanged event\n */\n function setFlashLoanPaused(bool paused) external {\n ensureAllowed(\"setFlashLoanPaused(bool)\");\n\n // Check if value is actually changing\n if (flashLoanPaused == paused) {\n return; // No change needed\n }\n\n emit FlashLoanPauseChanged(flashLoanPaused, paused);\n flashLoanPaused = paused;\n }\n\n /**\n * @notice Updates the label for a specific pool (excluding the Core Pool)\n * @param poolId ID of the pool to update\n * @param newLabel The new label for the pool\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string\n * @custom:event PoolLabelUpdated Emitted after the pool label is updated\n */\n function setPoolLabel(uint96 poolId, string calldata newLabel) external {\n ensureAllowed(\"setPoolLabel(uint96,string)\");\n\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n if (bytes(newLabel).length == 0) revert EmptyPoolLabel();\n\n PoolData storage pool = pools[poolId];\n\n if (keccak256(bytes(pool.label)) == keccak256(bytes(newLabel))) {\n return;\n }\n\n emit PoolLabelUpdated(poolId, pool.label, newLabel);\n pool.label = newLabel;\n }\n\n /**\n * @notice updates active status for a specific pool (excluding the Core Pool)\n * @param poolId id of the pool to update\n * @param active true to enable, false to disable\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\n * @custom:event PoolActiveStatusUpdated Emitted after the pool active status is updated.\n */\n function setPoolActive(uint96 poolId, bool active) external {\n ensureAllowed(\"setPoolActive(uint96,bool)\");\n\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n\n PoolData storage pool = pools[poolId];\n\n if (pool.isActive == active) {\n return;\n }\n\n emit PoolActiveStatusUpdated(poolId, pool.isActive, active);\n pool.isActive = active;\n }\n\n /**\n * @notice Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\n * @param poolId ID of the pool to update.\n * @param allowFallback True to allow fallback to Core Pool, false to disable.\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\n * @custom:event PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\n */\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external {\n ensureAllowed(\"setAllowCorePoolFallback(uint96,bool)\");\n\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n\n PoolData storage pool = pools[poolId];\n\n if (pool.allowCorePoolFallback == allowFallback) {\n return;\n }\n\n emit PoolFallbackStatusUpdated(poolId, pool.allowCorePoolFallback, allowFallback);\n pool.allowCorePoolFallback = allowFallback;\n }\n\n /**\n * @notice Updates the `isBorrowAllowed` flag for a market in a pool.\n * @param poolId The ID of the pool.\n * @param vToken The address of the market (vToken).\n * @param borrowAllowed The new borrow allowed status.\n * @custom:error PoolDoesNotExist Reverts if the pool ID is invalid.\n * @custom:error MarketConfigNotFound Reverts if the market is not listed in the pool.\n * @custom:event BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\n */\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external {\n ensureAllowed(\"setIsBorrowAllowed(uint96,address,bool)\");\n\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\n Market storage m = _poolMarkets[index];\n\n if (!m.isListed) {\n revert MarketConfigNotFound();\n }\n\n if (m.isBorrowAllowed == borrowAllowed) {\n return;\n }\n\n emit BorrowAllowedUpdated(poolId, vToken, m.isBorrowAllowed, borrowAllowed);\n m.isBorrowAllowed = borrowAllowed;\n }\n\n /**\n * @notice Sets the DeviationBoundedOracle for conservative CF-path pricing\n * @param newDeviationBoundedOracle The new DeviationBoundedOracle contract\n * @return uint256 0=success, otherwise a failure\n */\n function setDeviationBoundedOracle(\n IDeviationBoundedOracle newDeviationBoundedOracle\n ) external compareAddress(address(deviationBoundedOracle), address(newDeviationBoundedOracle)) returns (uint256) {\n ensureAllowed(\"setDeviationBoundedOracle(address)\");\n\n ensureNonzeroAddress(address(newDeviationBoundedOracle));\n\n IDeviationBoundedOracle oldDeviationBoundedOracle = deviationBoundedOracle;\n deviationBoundedOracle = newDeviationBoundedOracle;\n\n emit NewDeviationBoundedOracle(oldDeviationBoundedOracle, newDeviationBoundedOracle);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle\n * @param newOracle The new price oracle to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setPriceOracle(\n ResilientOracleInterface newOracle\n ) internal compareAddress(address(oracle), address(newOracle)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(newOracle));\n\n // Track the old oracle for the comptroller\n ResilientOracleInterface oldOracle = oracle;\n\n // Set comptroller's oracle to newOracle\n oracle = newOracle;\n\n // Emit NewPriceOracle(oldOracle, newOracle)\n emit NewPriceOracle(oldOracle, newOracle);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the close factor. Used by _setCloseFactor and setCloseFactor\n * @param newCloseFactorMantissa The new close factor to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setCloseFactor(\n uint256 newCloseFactorMantissa\n ) internal compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\n\n //-- Check close factor <= 0.9\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\n //-- Check close factor >= 0.05\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\n\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\n }\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the collateral factor and the liquidation threshold. Used by setCollateralFactor\n * @param poolId The ID of the pool.\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor to be set\n * @param newLiquidationThresholdMantissa The new liquidation threshold to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setCollateralFactor(\n uint96 poolId,\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) internal returns (uint256) {\n ensureNonzeroAddress(address(vToken));\n\n // Check if pool exists\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n\n // Verify market is listed in the pool\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, address(vToken))];\n ensureListed(market);\n\n //-- Check collateral factor <= 1\n if (newCollateralFactorMantissa > mantissaOne) {\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > mantissaOne) {\n return fail(Error.INVALID_LIQUIDATION_THRESHOLD, FailureInfo.SET_LIQUIDATION_THRESHOLD_VALIDATION);\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n return\n fail(\n Error.INVALID_LIQUIDATION_THRESHOLD,\n FailureInfo.COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\n );\n }\n\n // Set market's collateral factor to new collateral factor, remember old value\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n\n // Emit event with poolId, asset, old collateral factor, and new collateral factor\n emit NewCollateralFactor(poolId, vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n\n emit NewLiquidationThreshold(\n poolId,\n vToken,\n oldLiquidationThresholdMantissa,\n newLiquidationThresholdMantissa\n );\n }\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the liquidation incentive. Used by setLiquidationIncentive\n * @param poolId The ID of the pool.\n * @param vToken The market to set the Incentive for\n * @param newLiquidationIncentiveMantissa The new liquidation incentive to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setLiquidationIncentive(\n uint96 poolId,\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n )\n internal\n compareValue(\n _poolMarkets[getPoolMarketIndex(poolId, vToken)].liquidationIncentiveMantissa,\n newLiquidationIncentiveMantissa\n )\n returns (uint256)\n {\n // Check if pool exists\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n\n // Verify market is listed in the pool\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, vToken)];\n ensureListed(market);\n\n require(newLiquidationIncentiveMantissa >= mantissaOne, \"incentive < 1e18\");\n\n emit NewLiquidationIncentive(\n poolId,\n vToken,\n market.liquidationIncentiveMantissa,\n newLiquidationIncentiveMantissa\n );\n\n // Set liquidation incentive to new incentive\n market.liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the borrow caps. Used by _setMarketBorrowCaps and setMarketBorrowCaps\n * @param vTokens The markets to set the borrow caps on\n * @param newBorrowCaps The new borrow caps to be set\n */\n function __setMarketBorrowCaps(VToken[] memory vTokens, uint256[] memory newBorrowCaps) internal {\n ensureAllowed(\"_setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @dev Updates the supply caps. Used by _setMarketSupplyCaps and setMarketSupplyCaps\n * @param vTokens The markets to set the supply caps on\n * @param newSupplyCaps The new supply caps to be set\n */\n function __setMarketSupplyCaps(VToken[] memory vTokens, uint256[] memory newSupplyCaps) internal {\n ensureAllowed(\"_setMarketSupplyCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numSupplyCaps = newSupplyCaps.length;\n\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @dev Updates the prime token. Used by _setPrimeToken and setPrimeToken\n * @param _prime The new prime token to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setPrimeToken(IPrime _prime) internal returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(_prime));\n\n IPrime oldPrime = prime;\n prime = _prime;\n emit NewPrimeToken(oldPrime, _prime);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the forced liquidation. Used by _setForcedLiquidation and setForcedLiquidation\n * @param vTokenBorrowed The market to set the forced liquidation on\n * @param enable Whether to enable forced liquidations\n */\n function __setForcedLiquidation(address vTokenBorrowed, bool enable) internal {\n ensureAllowed(\"_setForcedLiquidation(address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(getCorePoolMarket(vTokenBorrowed));\n }\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @dev Updates the actions paused. Used by _setActionsPaused and setActionsPaused\n * @param markets_ The markets to set the actions paused on\n * @param actions_ The actions to set the paused state on\n * @param paused_ The new paused state to be set\n */\n function __setActionsPaused(address[] memory markets_, Action[] memory actions_, bool paused_) internal {\n ensureAllowed(\"_setActionsPaused(address[],uint8[],bool)\");\n\n uint256 numMarkets = markets_.length;\n uint256 numActions = actions_.length;\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { FacetBase } from \"./FacetBase.sol\";\n\n/**\n * @title XVSRewardsHelper\n * @author Venus\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\n */\ncontract XVSRewardsHelper is FacetBase {\n /// @notice Emitted when XVS is distributed to a borrower\n event DistributedBorrowerVenus(\n VToken indexed vToken,\n address indexed borrower,\n uint256 venusDelta,\n uint256 venusBorrowIndex\n );\n\n /// @notice Emitted when XVS is distributed to a supplier\n event DistributedSupplierVenus(\n VToken indexed vToken,\n address indexed supplier,\n uint256 venusDelta,\n uint256 venusSupplyIndex\n );\n\n /**\n * @notice Accrue XVS to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n */\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\n if (deltaBlocks != 0 && borrowSpeed != 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \"224\");\n borrowState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n borrowState.block = blockNumber;\n }\n }\n\n /**\n * @notice Accrue XVS to the market by updating the supply index\n * @param vToken The market whose supply index to update\n */\n function updateVenusSupplyIndex(address vToken) internal {\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n uint256 supplySpeed = venusSupplySpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\n if (deltaBlocks != 0 && supplySpeed != 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \"224\");\n supplyState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n supplyState.block = blockNumber;\n }\n }\n\n /**\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute XVS to\n */\n function distributeSupplierVenus(address vToken, address supplier) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 supplyIndex = venusSupplyState[vToken].index;\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\n // Update supplier's index to the current index since we are distributing accrued XVS\n venusSupplierIndex[vToken][supplier] = supplyIndex;\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n // Multiply of supplierTokens and supplierDelta\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\n // Addition of supplierAccrued and supplierDelta\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\n }\n\n /**\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute XVS to\n */\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 borrowIndex = venusBorrowState[vToken].index;\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\n // Update borrowers's index to the current index since we are distributing accrued XVS\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\n }\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n function diamondCut(FacetCut[] calldata _diamondCut) external;\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IFacetBase.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { Action } from \"../../../Comptroller/ComptrollerInterface.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\n\nenum WeightFunction {\n /// @notice Use the collateral factor of the asset for weighting\n USE_COLLATERAL_FACTOR,\n /// @notice Use the liquidation threshold of the asset for weighting\n USE_LIQUIDATION_THRESHOLD\n}\n\ninterface IFacetBase {\n /**\n * @notice The initial XVS rewards index for a market\n */\n function venusInitialIndex() external pure returns (uint224);\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param action Action id\n * @param market vToken address\n */\n function actionPaused(address market, Action action) external view returns (bool);\n\n /**\n * @notice Returns the XVS address\n * @return The address of XVS token\n */\n function getXVSAddress() external view returns (address);\n\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\n\n function corePoolId() external pure returns (uint96);\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IFlashLoanFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\n\ninterface IFlashLoanFacet {\n /// @notice Data structure to hold flash loan related data during execution\n struct FlashLoanFee {\n uint256[] totalFees;\n uint256[] protocolFees;\n }\n\n function executeFlashLoan(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n bytes memory param\n ) external;\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IMarketFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { WeightFunction } from \"./IFacetBase.sol\";\n\ninterface IMarketFacet {\n function isComptroller() external pure returns (bool);\n\n function liquidateCalculateSeizeTokens(\n address borrower,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function checkMembership(address account, VToken vToken) external view returns (bool);\n\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256);\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n function _supportMarket(VToken vToken) external returns (uint256);\n\n function supportMarket(VToken vToken) external returns (uint256);\n\n function isMarketListed(VToken vToken) external view returns (bool);\n\n function getAssetsIn(address account) external view returns (VToken[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function updateDelegate(address delegate, bool allowBorrows) external;\n\n function unlistMarket(address market) external returns (uint256);\n\n function createPool(string memory label) external returns (uint96);\n\n function enterPool(uint96 poolId) external;\n\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external;\n\n function removePoolMarket(uint96 poolId, address vToken) external;\n\n function markets(\n address vToken\n )\n external\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n );\n\n function poolMarkets(\n uint96 poolId,\n address vToken\n )\n external\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n );\n\n function hasValidPoolBorrows(address user, uint96 targetPoolId) external view returns (bool);\n\n function getCollateralFactor(address vToken) external view returns (uint256);\n\n function getLiquidationThreshold(address vToken) external view returns (uint256);\n\n function getLiquidationIncentive(address vToken) external view returns (uint256);\n\n function getEffectiveLtvFactor(\n address account,\n address vToken,\n WeightFunction weightingStrategy\n ) external view returns (uint256);\n\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\n\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IPolicyFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\n\ninterface IPolicyFacet {\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\n\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\n\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\n\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount\n ) external returns (uint256);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount,\n uint256 borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount,\n uint256 seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external returns (uint256);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external;\n\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256);\n\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\n\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256);\n\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external;\n\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall);\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\n\ninterface IRewardFacet {\n function claimVenus(address holder) external;\n\n function claimVenus(address holder, VToken[] calldata vTokens) external;\n\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\n\n function claimVenusAsCollateral(address holder) external;\n\n function _grantXVS(address recipient, uint256 amount) external;\n\n function getXVSVTokenAddress() external view returns (address);\n\n function claimVenus(\n address[] calldata holders,\n VToken[] calldata vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) external;\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256);\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { VAIControllerInterface } from \"../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterface } from \"../../../Comptroller/ComptrollerLensInterface.sol\";\nimport { IPrime } from \"../../../Tokens/Prime/IPrime.sol\";\n\ninterface ISetterFacet {\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\n\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\n\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\n\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256);\n\n function setCollateralFactor(\n uint96 poolId,\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256);\n\n function setLiquidationIncentive(\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n ) external returns (uint256);\n\n function setLiquidationIncentive(\n uint96 poolId,\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n ) external returns (uint256);\n\n function _setLiquidatorContract(address newLiquidatorContract_) external;\n\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\n\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setProtocolPaused(bool state) external returns (bool);\n\n function setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\n\n function _setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\n\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\n\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\n\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\n\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256);\n\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external returns (uint256);\n\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\n\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\n\n function _setForcedLiquidation(address vToken, bool enable) external;\n\n function setPrimeToken(IPrime _prime) external returns (uint256);\n\n function _setPrimeToken(IPrime _prime) external returns (uint);\n\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external;\n\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external;\n\n function _setXVSToken(address xvs_) external;\n\n function _setXVSVToken(address xvsVToken_) external;\n\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external;\n\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external;\n\n function setPoolActive(uint96 poolId, bool active) external;\n\n function setPoolLabel(uint96 poolId, string calldata newLabel) external;\n\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external;\n\n function setFlashLoanPaused(bool paused) external;\n\n function setDeviationBoundedOracle(IDeviationBoundedOracle newDeviationBoundedOracle) external returns (uint256);\n}\n" + }, + "contracts/Comptroller/legacy/ComptrollerInterfaceR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"../../Tokens/VTokens/VToken.sol\";\nimport { VAIControllerInterface } from \"../../Tokens/VAI/VAIControllerInterface.sol\";\n\nenum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n}\n\ninterface ComptrollerInterfaceR1 {\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() external pure returns (bool);\n\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\n\n function exitMarket(address vToken) external returns (uint);\n\n /*** Policy Hooks ***/\n\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external returns (uint);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function getXVSAddress() external view returns (address);\n\n function markets(address) external view returns (bool, uint);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function claimVenus(address) external;\n\n function venusAccrued(address) external view returns (uint);\n\n function venusSupplySpeeds(address) external view returns (uint);\n\n function venusBorrowSpeeds(address) external view returns (uint);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function venusSupplierIndex(address, address) external view returns (uint);\n\n function venusInitialIndex() external view returns (uint224);\n\n function venusBorrowerIndex(address, address) external view returns (uint);\n\n function venusBorrowState(address) external view returns (uint224, uint32);\n\n function venusSupplyState(address) external view returns (uint224, uint32);\n\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\n\n function vaiController() external view returns (VAIControllerInterface);\n\n function liquidationIncentiveMantissa() external view returns (uint);\n\n function protocolPaused() external view returns (bool);\n\n function actionPaused(address market, Action action) external view returns (bool);\n\n function mintedVAIs(address user) external view returns (uint);\n\n function vaiMintRate() external view returns (uint);\n}\n\ninterface IVAIVault {\n function updatePendingRewards() external;\n}\n\ninterface IComptroller {\n function liquidationIncentiveMantissa() external view returns (uint);\n\n /*** Treasury Data ***/\n function treasuryAddress() external view returns (address);\n\n function treasuryPercent() external view returns (uint);\n}\n" + }, + "contracts/Comptroller/legacy/ComptrollerLensInterfaceR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../Tokens/VTokens/VToken.sol\";\n\ninterface ComptrollerLensInterfaceR1 {\n function liquidateCalculateSeizeTokens(\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function liquidateVAICalculateSeizeTokens(\n address comptroller,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function getHypotheticalAccountLiquidity(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount\n ) external view returns (uint, uint, uint);\n}\n" + }, + "contracts/Comptroller/legacy/ComptrollerStorageR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"../../Tokens/VTokens/VToken.sol\";\nimport { VAIControllerInterface } from \"../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterfaceR1 } from \"./ComptrollerLensInterfaceR1.sol\";\nimport { IPrime } from \"../../Tokens/Prime/IPrime.sol\";\n\ncontract UnitrollerAdminStorageR1 {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of Unitroller\n */\n address public comptrollerImplementation;\n\n /**\n * @notice Pending brains of Unitroller\n */\n address public pendingComptrollerImplementation;\n}\n\ncontract ComptrollerV1StorageR1 is UnitrollerAdminStorageR1 {\n /**\n * @notice Oracle which gives the price of any given asset\n */\n ResilientOracleInterface public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n */\n uint256 public liquidationIncentiveMantissa;\n\n /**\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\n */\n uint256 public maxAssets;\n\n /**\n * @notice Per-account mapping of \"assets you are in\", capped by maxAssets\n */\n mapping(address => VToken[]) public accountAssets;\n\n struct Market {\n /// @notice Whether or not this market is listed\n bool isListed;\n /**\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\n * For instance, 0.9 to allow borrowing 90% of collateral value.\n * Must be between 0 and 1, and stored as a mantissa.\n */\n uint256 collateralFactorMantissa;\n /// @notice Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n /// @notice Whether or not this market receives XVS\n bool isVenus;\n }\n\n /**\n * @notice Official mapping of vTokens -> Market metadata\n * @dev Used e.g. to determine if a market is supported\n */\n mapping(address => Market) public markets;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n address public pauseGuardian;\n\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\n bool private _mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool private _borrowGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal transferGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal seizeGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal borrowGuardianPaused;\n\n struct VenusMarketState {\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\n uint224 index;\n /// @notice The block number the index was last updated at\n uint32 block;\n }\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice The rate at which the flywheel distributes XVS, per block\n uint256 internal venusRate;\n\n /// @notice The portion of venusRate that each market currently receives\n mapping(address => uint256) internal venusSpeeds;\n\n /// @notice The Venus market supply state for each market\n mapping(address => VenusMarketState) public venusSupplyState;\n\n /// @notice The Venus market borrow state for each market\n mapping(address => VenusMarketState) public venusBorrowState;\n\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\n\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\n\n /// @notice The XVS accrued but not yet transferred to each user\n mapping(address => uint256) public venusAccrued;\n\n /// @notice The Address of VAIController\n VAIControllerInterface public vaiController;\n\n /// @notice The minted VAI amount to each user\n mapping(address => uint256) public mintedVAIs;\n\n /// @notice VAI Mint Rate as a percentage\n uint256 public vaiMintRate;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n bool public mintVAIGuardianPaused;\n bool public repayVAIGuardianPaused;\n\n /**\n * @notice Pause/Unpause whole protocol actions\n */\n bool public protocolPaused;\n\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\n uint256 private venusVAIRate;\n}\n\ncontract ComptrollerV2StorageR1 is ComptrollerV1StorageR1 {\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\n uint256 public venusVAIVaultRate;\n\n // address of VAI Vault\n address public vaiVaultAddress;\n\n // start block of release to VAI Vault\n uint256 public releaseStartBlock;\n\n // minimum release amount to VAI Vault\n uint256 public minReleaseAmount;\n}\n\ncontract ComptrollerV3StorageR1 is ComptrollerV2StorageR1 {\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\n address public borrowCapGuardian;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\n mapping(address => uint256) public borrowCaps;\n}\n\ncontract ComptrollerV4StorageR1 is ComptrollerV3StorageR1 {\n /// @notice Treasury Guardian address\n address public treasuryGuardian;\n\n /// @notice Treasury address\n address public treasuryAddress;\n\n /// @notice Fee percent of accrued interest with decimal 18\n uint256 public treasuryPercent;\n}\n\ncontract ComptrollerV5StorageR1 is ComptrollerV4StorageR1 {\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\n mapping(address => uint256) private venusContributorSpeeds;\n\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\n mapping(address => uint256) private lastContributorBlock;\n}\n\ncontract ComptrollerV6StorageR1 is ComptrollerV5StorageR1 {\n address public liquidatorContract;\n}\n\ncontract ComptrollerV7StorageR1 is ComptrollerV6StorageR1 {\n ComptrollerLensInterfaceR1 public comptrollerLens;\n}\n\ncontract ComptrollerV8StorageR1 is ComptrollerV7StorageR1 {\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\n mapping(address => uint256) public supplyCaps;\n}\n\ncontract ComptrollerV9StorageR1 is ComptrollerV8StorageR1 {\n /// @notice AccessControlManager address\n address internal accessControl;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\n}\n\ncontract ComptrollerV10StorageR1 is ComptrollerV9StorageR1 {\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public venusBorrowSpeeds;\n\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public venusSupplySpeeds;\n}\n\ncontract ComptrollerV11StorageR1 is ComptrollerV10StorageR1 {\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\n mapping(address => mapping(address => bool)) public approvedDelegates;\n}\n\ncontract ComptrollerV12StorageR1 is ComptrollerV11StorageR1 {\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\n mapping(address => bool) public isForcedLiquidationEnabled;\n}\n\ncontract ComptrollerV13StorageR1 is ComptrollerV12StorageR1 {\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\n }\n\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\n // facet addresses\n address[] internal _facetAddresses;\n}\n\ncontract ComptrollerV14StorageR1 is ComptrollerV13StorageR1 {\n /// @notice Prime token address\n IPrime public prime;\n}\n\ncontract ComptrollerV15StorageR1 is ComptrollerV14StorageR1 {\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\n}\n\ncontract ComptrollerV16StorageR1 is ComptrollerV15StorageR1 {\n /// @notice The XVS token contract address\n address internal xvs;\n\n /// @notice The XVS vToken contract address\n address internal xvsVToken;\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/DiamondConsolidatedR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { MarketFacetR1 } from \"./facets/MarketFacetR1.sol\";\nimport { PolicyFacetR1 } from \"./facets/PolicyFacetR1.sol\";\nimport { RewardFacetR1 } from \"./facets/RewardFacetR1.sol\";\nimport { SetterFacetR1 } from \"./facets/SetterFacetR1.sol\";\nimport { DiamondR1 } from \"./DiamondR1.sol\";\n\n/**\n * @title DiamondConsolidated\n * @author Venus\n * @notice This contract contains the functions defined in the different facets of the Diamond, plus the getters to the public variables.\n * This contract cannot be deployed, due to its size. Its main purpose is to allow the easy generation of an ABI and the typechain to interact with the\n * Unitroller contract in a simple way\n */\ncontract DiamondConsolidatedR1 is DiamondR1, MarketFacetR1, PolicyFacetR1, RewardFacetR1, SetterFacetR1 {}\n" + }, + "contracts/Comptroller/legacy/Diamond/DiamondR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IDiamondCutR1 } from \"./interfaces/IDiamondCutR1.sol\";\nimport { Unitroller } from \"../../Unitroller.sol\";\nimport { ComptrollerV16StorageR1 } from \"../ComptrollerStorageR1.sol\";\n\n/**\n * @title Diamond\n * @author Venus\n * @notice This contract contains functions related to facets\n */\ncontract DiamondR1 is IDiamondCutR1, ComptrollerV16StorageR1 {\n /// @notice Emitted when functions are added, replaced or removed to facets\n event DiamondCut(IDiamondCutR1.FacetCut[] _diamondCut);\n\n struct Facet {\n address facetAddress;\n bytes4[] functionSelectors;\n }\n\n /**\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\n * @param unitroller Address of the unitroller\n */\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n /**\n * @notice To add function selectors to the facet's mapping\n * @dev Allows the contract admin to add function selectors\n * @param diamondCut_ IDiamondCutR1 contains facets address, action and function selectors\n */\n function diamondCut(IDiamondCutR1.FacetCut[] memory diamondCut_) public {\n require(msg.sender == admin, \"only unitroller admin can\");\n libDiamondCut(diamondCut_);\n }\n\n /**\n * @notice Get all function selectors mapped to the facet address\n * @param facet Address of the facet\n * @return selectors Array of function selectors\n */\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\n return _facetFunctionSelectors[facet].functionSelectors;\n }\n\n /**\n * @notice Get facet position in the _facetFunctionSelectors through facet address\n * @param facet Address of the facet\n * @return Position of the facet\n */\n function facetPosition(address facet) external view returns (uint256) {\n return _facetFunctionSelectors[facet].facetAddressPosition;\n }\n\n /**\n * @notice Get all facet addresses\n * @return facetAddresses Array of facet addresses\n */\n function facetAddresses() external view returns (address[] memory) {\n return _facetAddresses;\n }\n\n /**\n * @notice Get facet address and position through function selector\n * @param functionSelector function selector\n * @return FacetAddressAndPosition facet address and position\n */\n function facetAddress(\n bytes4 functionSelector\n ) external view returns (ComptrollerV16StorageR1.FacetAddressAndPosition memory) {\n return _selectorToFacetAndPosition[functionSelector];\n }\n\n /**\n * @notice Get all facets address and their function selector\n * @return facets_ Array of Facet\n */\n function facets() external view returns (Facet[] memory) {\n uint256 facetsLength = _facetAddresses.length;\n Facet[] memory facets_ = new Facet[](facetsLength);\n for (uint256 i; i < facetsLength; ++i) {\n address facet = _facetAddresses[i];\n facets_[i].facetAddress = facet;\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\n }\n return facets_;\n }\n\n /**\n * @notice To add function selectors to the facets' mapping\n * @param diamondCut_ IDiamondCutR1 contains facets address, action and function selectors\n */\n function libDiamondCut(IDiamondCutR1.FacetCut[] memory diamondCut_) internal {\n uint256 diamondCutLength = diamondCut_.length;\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\n IDiamondCutR1.FacetCutAction action = diamondCut_[facetIndex].action;\n if (action == IDiamondCutR1.FacetCutAction.Add) {\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCutR1.FacetCutAction.Replace) {\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCutR1.FacetCutAction.Remove) {\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n }\n emit DiamondCut(diamondCut_);\n }\n\n /**\n * @notice Add function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to add in the mapping\n */\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress == address(0), \"LibDiamondCut: Can't add function that already exists\");\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to replace in the mapping\n */\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress != facetAddress, \"LibDiamondCut: Can't replace function with same function\");\n removeFunction(oldFacetAddress, selector);\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Remove function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to remove in the mapping\n */\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n uint256 functionSelectorsLength = functionSelectors.length;\n require(functionSelectorsLength != 0, \"LibDiamondCut: No selectors in facet to cut\");\n // if function does not exist then do nothing and revert\n require(facetAddress == address(0), \"LibDiamondCut: Remove facet address must be address(0)\");\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n removeFunction(oldFacetAddress, selector);\n }\n }\n\n /**\n * @notice Add new facet to the proxy\n * @param facetAddress Address of the facet\n */\n function addFacet(address facetAddress) internal {\n enforceHasContractCode(facetAddress, \"Diamond: New facet has no code\");\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\n _facetAddresses.push(facetAddress);\n }\n\n /**\n * @notice Add function selector to the facet's address mapping\n * @param selector funciton selector need to be added\n * @param selectorPosition funciton selector position\n * @param facetAddress Address of the facet\n */\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\n }\n\n /**\n * @notice Remove function selector to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param selector function selectors need to remove in the mapping\n */\n function removeFunction(address facetAddress, bytes4 selector) internal {\n require(facetAddress != address(0), \"LibDiamondCut: Can't remove function that doesn't exist\");\n\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\n // if not the same then replace selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\n delete _selectorToFacetAndPosition[selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\n }\n _facetAddresses.pop();\n delete _facetFunctionSelectors[facetAddress];\n }\n }\n\n /**\n * @dev Ensure that the given address has contract code deployed\n * @param _contract The address to check for contract code\n * @param _errorMessage The error message to display if the contract code is not deployed\n */\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\n uint256 contractSize;\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize != 0, _errorMessage);\n }\n\n // Find facet for function that is called and execute the\n // function if a facet is found and return any value.\n fallback() external {\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\n require(facet != address(0), \"Diamond: Function does not exist\");\n // Execute public function from facet using delegatecall and return any value.\n assembly {\n // copy function selector and any arguments\n calldatacopy(0, 0, calldatasize())\n // execute function call using the facet\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\n // get any return value\n returndatacopy(0, 0, returndatasize())\n // return any return value or error back to the caller\n switch result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/FacetBaseR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { ComptrollerErrorReporter } from \"../../../../Utils/ErrorReporter.sol\";\nimport { ExponentialNoError } from \"../../../../Utils/ExponentialNoError.sol\";\nimport { IVAIVault, Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { ComptrollerV16StorageR1 } from \"../../ComptrollerStorageR1.sol\";\n\n/**\n * @title FacetBase\n * @author Venus\n * @notice This facet contract contains functions related to access and checks\n */\ncontract FacetBaseR1 is ComptrollerV16StorageR1, ExponentialNoError, ComptrollerErrorReporter {\n using SafeERC20 for IERC20;\n\n /// @notice The initial Venus index for a market\n uint224 public constant venusInitialIndex = 1e36;\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\n // closeFactorMantissa must not exceed this value\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when XVS is distributed to VAI Vault\n event DistributedVAIVaultVenus(uint256 amount);\n\n /// @notice Reverts if the protocol is paused\n function checkProtocolPauseState() internal view {\n require(!protocolPaused, \"protocol is paused\");\n }\n\n /// @notice Reverts if a certain action is paused on a market\n function checkActionPauseState(address market, Action action) internal view {\n require(!actionPaused(market, action), \"action is paused\");\n }\n\n /// @notice Reverts if the caller is not admin\n function ensureAdmin() internal view {\n require(msg.sender == admin, \"only admin can\");\n }\n\n /// @notice Checks the passed address is nonzero\n function ensureNonzeroAddress(address someone) internal pure {\n require(someone != address(0), \"can't be zero address\");\n }\n\n /// @notice Reverts if the market is not listed\n function ensureListed(Market storage market) internal view {\n require(market.isListed, \"market not listed\");\n }\n\n /// @notice Reverts if the caller is neither admin nor the passed address\n function ensureAdminOr(address privilegedAddress) internal view {\n require(msg.sender == admin || msg.sender == privilegedAddress, \"access denied\");\n }\n\n /// @notice Checks the caller is allowed to call the specified fuction\n function ensureAllowed(string memory functionSig) internal view {\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \"access denied\");\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param action Action id\n * @param market vToken address\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][uint256(action)];\n }\n\n /**\n * @notice Get the latest block number\n */\n function getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Get the latest block number with the safe32 check\n */\n function getBlockNumberAsUint32() internal view returns (uint32) {\n return safe32(getBlockNumber(), \"block # > 32 bits\");\n }\n\n /**\n * @notice Transfer XVS to VAI Vault\n */\n function releaseToVault() internal {\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\n return;\n }\n\n IERC20 xvs_ = IERC20(xvs);\n\n uint256 xvsBalance = xvs_.balanceOf(address(this));\n if (xvsBalance == 0) {\n return;\n }\n\n uint256 actualAmount;\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\n // releaseAmount = venusVAIVaultRate * deltaBlocks\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\n\n if (xvsBalance >= releaseAmount_) {\n actualAmount = releaseAmount_;\n } else {\n actualAmount = xvsBalance;\n }\n\n if (actualAmount < minReleaseAmount) {\n return;\n }\n\n releaseStartBlock = getBlockNumber();\n\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\n emit DistributedVAIVaultVenus(actualAmount);\n\n IVAIVault(vaiVaultAddress).updatePendingRewards();\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return (possible error code,\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidityInternal(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) internal view returns (Error, uint256, uint256) {\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\n address(this),\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount\n );\n return (Error(err), liquidity, shortfall);\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n * @return Success indicator for whether the market was entered\n */\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n ensureListed(marketToJoin);\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return Error.NO_ERROR;\n }\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n\n return Error.NO_ERROR;\n }\n\n /**\n * @notice Checks for the user is allowed to redeem tokens\n * @param vToken Address of the market\n * @param redeemer Address of the user\n * @param redeemTokens Amount of tokens to redeem\n * @return Success indicator for redeem is allowed or not\n */\n function redeemAllowedInternal(\n address vToken,\n address redeemer,\n uint256 redeemTokens\n ) internal view returns (uint256) {\n ensureListed(markets[vToken]);\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!markets[vToken].accountMembership[redeemer]) {\n return uint256(Error.NO_ERROR);\n }\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Returns the XVS address\n * @return The address of XVS token\n */\n function getXVSAddress() external view returns (address) {\n return xvs;\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/MarketFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { IMarketFacetR1 } from \"../interfaces/IMarketFacetR1.sol\";\nimport { FacetBaseR1 } from \"./FacetBaseR1.sol\";\n\n/**\n * @title MarketFacet\n * @author Venus\n * @dev This facet contains all the methods related to the market's management in the pool\n * @notice This facet contract contains functions regarding markets\n */\ncontract MarketFacetR1 is IMarketFacetR1, FacetBaseR1 {\n /// @notice Emitted when an admin supports a market\n event MarketListed(VToken indexed vToken);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account\n event DelegateUpdated(address indexed approver, address indexed delegate, bool approved);\n\n /// @notice Emitted when an admin unlists a market\n event MarketUnlisted(address indexed vToken);\n\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() public pure returns (bool) {\n return true;\n }\n\n /**\n * @notice Returns the assets an account has entered\n * @param account The address of the account to pull assets for\n * @return A dynamic list with the assets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n uint256 len;\n VToken[] memory _accountAssets = accountAssets[account];\n uint256 _accountAssetsLength = _accountAssets.length;\n\n VToken[] memory assetsIn = new VToken[](_accountAssetsLength);\n\n for (uint256 i; i < _accountAssetsLength; ++i) {\n Market storage market = markets[address(_accountAssets[i])];\n if (market.isListed) {\n assetsIn[len] = _accountAssets[i];\n ++len;\n }\n }\n\n assembly {\n mstore(assetsIn, len)\n }\n\n return assetsIn;\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market\n * @return The list of market addresses\n */\n function getAllMarkets() external view returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\n address(this),\n vTokenBorrowed,\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\n address(this),\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Returns whether the given account is entered in the given asset\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the asset, otherwise false\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return markets[address(vToken)].accountMembership[account];\n }\n\n /**\n * @notice Check if a market is marked as listed (active)\n * @param vToken vToken Address for the market to check\n * @return listed True if listed otherwise false\n */\n function isMarketListed(VToken vToken) external view returns (bool) {\n return markets[address(vToken)].isListed;\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return Success indicator for whether each corresponding market was entered\n */\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\n * @param market The address of the market (vToken) to unlist\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function unlistMarket(address market) external returns (uint256) {\n ensureAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.UNLIST_MARKET_NOT_LISTED);\n }\n\n require(actionPaused(market, Action.BORROW), \"borrow action is not paused\");\n require(actionPaused(market, Action.MINT), \"mint action is not paused\");\n require(actionPaused(market, Action.REDEEM), \"redeem action is not paused\");\n require(actionPaused(market, Action.REPAY), \"repay action is not paused\");\n require(actionPaused(market, Action.ENTER_MARKET), \"enter market action is not paused\");\n require(actionPaused(market, Action.LIQUIDATE), \"liquidate action is not paused\");\n require(actionPaused(market, Action.SEIZE), \"seize action is not paused\");\n require(actionPaused(market, Action.TRANSFER), \"transfer action is not paused\");\n require(actionPaused(market, Action.EXIT_MARKET), \"exit market action is not paused\");\n\n require(borrowCaps[market] == 0, \"borrow cap is not 0\");\n require(supplyCaps[market] == 0, \"supply cap is not 0\");\n\n require(_market.collateralFactorMantissa == 0, \"collateral factor is not 0\");\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow\n * @param vTokenAddress The address of the asset to be removed\n * @return Whether or not the account successfully exited the market\n */\n function exitMarket(address vTokenAddress) external returns (uint256) {\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\n require(oErr == 0, \"getAccountSnapshot failed\"); // semi-opaque error code\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\n if (allowed != 0) {\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\n }\n\n Market storage marketToExit = markets[address(vToken)];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return uint256(Error.NO_ERROR);\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n uint256 i;\n for (; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n userAssetList[i] = userAssetList[len - 1];\n userAssetList.pop();\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(i < len);\n\n emit MarketExited(vToken, msg.sender);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _supportMarket to support the Isolated Lending Comptroller Interface\n * @param vToken The address of the market (token) to list\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function supportMarket(VToken vToken) external returns (uint256) {\n return __supportMarket(vToken);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Allows a privileged role to add and list markets to the Comptroller\n * @param vToken The address of the market (token) to list\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _supportMarket(VToken vToken) external returns (uint256) {\n return __supportMarket(vToken);\n }\n\n /**\n * @notice Grants or revokes the borrowing or redeeming delegate rights to / from an account\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\n * will see the debt on their account\n * Upon a delegated redeem, the delegate will receive the redeemed amount and the approver\n * will see a deduction in his vToken balance\n * @param delegate The address to update the rights for\n * @param approved Whether to grant (true) or revoke (false) the borrowing or redeeming rights\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n require(approvedDelegates[msg.sender][delegate] != approved, \"Delegation status unchanged\");\n\n _updateDelegate(msg.sender, delegate, approved);\n }\n\n function _updateDelegate(address approver, address delegate, bool approved) internal {\n approvedDelegates[approver][delegate] = approved;\n emit DelegateUpdated(approver, delegate, approved);\n }\n\n function _addMarketInternal(VToken vToken) internal {\n uint256 allMarketsLength = allMarkets.length;\n for (uint256 i; i < allMarketsLength; ++i) {\n require(allMarkets[i] != vToken, \"already added\");\n }\n allMarkets.push(vToken);\n }\n\n function _initializeMarket(address vToken) internal {\n uint32 blockNumber = getBlockNumberAsUint32();\n\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = venusInitialIndex;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = venusInitialIndex;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n function __supportMarket(VToken vToken) internal returns (uint256) {\n ensureAllowed(\"_supportMarket(address)\");\n\n if (markets[address(vToken)].isListed) {\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\n }\n\n vToken.isVToken(); // Sanity check to make sure its really a VToken\n\n // Note that isVenus is not in active use anymore\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.isVenus = false;\n newMarket.collateralFactorMantissa = 0;\n\n _addMarketInternal(vToken);\n _initializeMarket(address(vToken));\n\n emit MarketListed(vToken);\n\n return uint256(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/PolicyFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { IPolicyFacetR1 } from \"../interfaces/IPolicyFacetR1.sol\";\n\nimport { XVSRewardsHelperR1 } from \"./XVSRewardsHelperR1.sol\";\n\n/**\n * @title PolicyFacet\n * @author Venus\n * @dev This facet contains all the hooks used while transferring the assets\n * @notice This facet contract contains all the external pre-hook functions related to vToken\n */\ncontract PolicyFacetR1 is IPolicyFacetR1, XVSRewardsHelperR1 {\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.MINT);\n ensureListed(markets[vToken]);\n\n uint256 supplyCap = supplyCaps[vToken];\n require(supplyCap != 0, \"market supply cap is 0\");\n\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n require(nextTotalSupply <= supplyCap, \"market supply cap reached\");\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, minter);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being minted\n * @param minter The address minting the tokens\n * @param actualMintAmount The amount of the underlying asset being minted\n * @param mintTokens The number of tokens being minted\n */\n // solhint-disable-next-line no-unused-vars\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(minter, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REDEEM);\n\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, redeemer);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being redeemed\n * @param redeemer The address redeeming the tokens\n * @param redeemAmount The amount of the underlying asset being redeemed\n * @param redeemTokens The number of tokens being redeemed\n */\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\n require(redeemTokens != 0 || redeemAmount == 0, \"redeemTokens zero\");\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.BORROW);\n ensureListed(markets[vToken]);\n\n uint256 borrowCap = borrowCaps[vToken];\n require(borrowCap != 0, \"market borrow cap is 0\");\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n require(msg.sender == vToken, \"sender must be vToken\");\n\n // attempt to add borrower to the market\n Error err = addToMarketInternal(VToken(vToken), borrower);\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n }\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n return uint256(Error.PRICE_ERROR);\n }\n\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\n require(nextTotalBorrows <= borrowCap, \"market borrow cap reached\");\n\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset whose underlying is being borrowed\n * @param borrower The address borrowing the underlying\n * @param borrowAmount The amount of the underlying asset requested to borrow\n */\n // solhint-disable-next-line no-unused-vars\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param payer The account which would repay the asset\n * @param borrower The account which borrowed the asset\n * @param repayAmount The amount of the underlying asset the account would repay\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function repayBorrowAllowed(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 repayAmount // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REPAY);\n ensureListed(markets[vToken]);\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being repaid\n * @param payer The address repaying the borrow\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n */\n function repayBorrowVerify(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n */\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256) {\n checkProtocolPauseState();\n\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\n return uint256(Error.UNAUTHORIZED);\n }\n\n ensureListed(markets[vTokenCollateral]);\n\n uint256 borrowBalance;\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n } else {\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\n }\n\n if (isForcedLiquidationEnabled[vTokenBorrowed] || isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n return uint(Error.TOO_MUCH_REPAY);\n }\n return uint(Error.NO_ERROR);\n }\n\n /* The borrower must have shortfall in order to be liquidatable */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(borrower, VToken(address(0)), 0, 0);\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall == 0) {\n return uint256(Error.INSUFFICIENT_SHORTFALL);\n }\n\n // The liquidator may not repay more than what is allowed by the closeFactor\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\n return uint256(Error.TOO_MUCH_REPAY);\n }\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n * @param seizeTokens The amount of collateral token that will be seized\n */\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n // We've added VAIController as a borrowed token list check for seize\n ensureListed(market);\n\n if (!market.accountMembership[borrower]) {\n return uint256(Error.MARKET_NOT_COLLATERAL);\n }\n\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n }\n\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\n return uint256(Error.COMPTROLLER_MISMATCH);\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vTokenCollateral);\n distributeSupplierVenus(vTokenCollateral, borrower);\n distributeSupplierVenus(vTokenCollateral, liquidator);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, src);\n distributeSupplierVenus(vToken, dst);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being transferred\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n */\n // solhint-disable-next-line no-unused-vars\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(src, vToken);\n prime.accrueInterestAndUpdateScore(dst, vToken);\n }\n }\n\n /**\n * @notice Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\n * @param account The account get liquidity for\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n * account shortfall below collateral requirements)\n */\n function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) {\n return _getAccountLiquidity(account);\n }\n\n /**\n * @notice Determine the current account liquidity wrt collateral requirements\n * @param account The account get liquidity for\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n * account shortfall below collateral requirements)\n */\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\n return _getAccountLiquidity(account);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return (possible error code (semi-opaque),\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n // setter functionality\n /**\n * @notice Set XVS speed for a single market\n * @dev Allows the contract admin to set XVS speed for a market\n * @param vTokens The market whose XVS speed to update\n * @param supplySpeeds New XVS speed for supply\n * @param borrowSpeeds New XVS speed for borrow\n */\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external {\n ensureAdmin();\n\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid input\");\n\n for (uint256 i; i < numTokens; ++i) {\n ensureNonzeroAddress(address(vTokens[i]));\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n function _getAccountLiquidity(address account) internal view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n account,\n VToken(address(0)),\n 0,\n 0\n );\n\n return (uint256(err), liquidity, shortfall);\n }\n\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n ensureListed(markets[address(vToken)]);\n\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n\n updateVenusSupplyIndex(address(vToken));\n // Update speed and emit event\n venusSupplySpeeds[address(vToken)] = supplySpeed;\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/RewardFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { IRewardFacetR1 } from \"../interfaces/IRewardFacetR1.sol\";\nimport { XVSRewardsHelperR1 } from \"./XVSRewardsHelperR1.sol\";\nimport { VBep20Interface } from \"../../../../Tokens/VTokens/VTokenInterfaces.sol\";\n\n/**\n * @title RewardFacet\n * @author Venus\n * @dev This facet contains all the methods related to the reward functionality\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\n */\ncontract RewardFacetR1 is IRewardFacetR1, XVSRewardsHelperR1 {\n /// @notice Emitted when Venus is granted by admin\n event VenusGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when XVS are seized for the holder\n event VenusSeized(address indexed holder, uint256 amount);\n\n using SafeERC20 for IERC20;\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets and VAI\n * @param holder The address to claim XVS for\n */\n function claimVenus(address holder) public {\n return claimVenus(holder, allMarkets);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in the specified markets\n * @param holder The address to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n */\n function claimVenus(address holder, VToken[] memory vTokens) public {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, vTokens, true, true);\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\n claimVenus(holders, vTokens, borrowers, suppliers, false);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\n * @param holder The address to claim XVS for\n */\n function claimVenusAsCollateral(address holder) external {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, allMarkets, true, true, true);\n }\n\n /**\n * @notice Transfer XVS to the user with user's shortfall considered\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\n * @param user The address of the user to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n * @param shortfall The shortfall of the user\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\n * @return The amount of XVS which was NOT transferred to the user\n */\n function grantXVSInternal(\n address user,\n uint256 amount,\n uint256 shortfall,\n bool collateral\n ) internal returns (uint256) {\n // If the user is blacklisted, they can't get XVS rewards\n require(\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\n \"Blacklisted\"\n );\n\n IERC20 xvs_ = IERC20(xvs);\n\n if (amount == 0 || amount > xvs_.balanceOf(address(this))) {\n return amount;\n }\n\n if (shortfall == 0) {\n xvs_.safeTransfer(user, amount);\n return 0;\n }\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\n // anything, otherwise, we will transfer the pending xvs as collateral to\n // vXVS token and mint vXVS for the user\n //\n // If mintBehalf failed, don't grant any xvs\n require(collateral, \"bankrupt\");\n\n address xvsVToken_ = xvsVToken;\n\n xvs_.safeApprove(xvsVToken_, 0);\n xvs_.safeApprove(xvsVToken_, amount);\n require(VBep20Interface(xvsVToken_).mintBehalf(user, amount) == uint256(Error.NO_ERROR), \"mint behalf error\");\n\n // set venusAccrued[user] to 0\n return 0;\n }\n\n /*** Venus Distribution Admin ***/\n\n /**\n * @notice Transfer XVS to the recipient\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\n * Note: If there is not enough XVS, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n */\n function _grantXVS(address recipient, uint256 amount) external {\n ensureAdmin();\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\n require(amountLeft == 0, \"no xvs\");\n emit VenusGranted(recipient, amount);\n }\n\n /**\n * @dev Seize XVS tokens from the specified holders and transfer to recipient\n * @notice Seize XVS rewards allocated to holders\n * @param holders Addresses of the XVS holders\n * @param recipient Address of the XVS token recipient\n * @return The total amount of XVS tokens seized and transferred to recipient\n */\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256) {\n ensureAllowed(\"seizeVenus(address[],address)\");\n\n uint256 holdersLength = holders.length;\n uint256 totalHoldings;\n\n updateAndDistributeRewardsInternal(holders, allMarkets, true, true);\n for (uint256 j; j < holdersLength; ++j) {\n address holder = holders[j];\n uint256 userHolding = venusAccrued[holder];\n\n if (userHolding != 0) {\n totalHoldings += userHolding;\n delete venusAccrued[holder];\n }\n\n emit VenusSeized(holder, userHolding);\n }\n\n if (totalHoldings != 0) {\n IERC20(xvs).safeTransfer(recipient, totalHoldings);\n emit VenusGranted(recipient, totalHoldings);\n }\n\n return totalHoldings;\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\n */\n function claimVenus(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) public {\n uint256 holdersLength = holders.length;\n\n updateAndDistributeRewardsInternal(holders, vTokens, borrowers, suppliers);\n for (uint256 j; j < holdersLength; ++j) {\n address holder = holders[j];\n\n // If there is a positive shortfall, the XVS reward is accrued,\n // but won't be granted to this holder\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(holder, VToken(address(0)), 0, 0);\n\n uint256 value = venusAccrued[holder];\n delete venusAccrued[holder];\n\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\n\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\n if (returnAmount != 0) {\n venusAccrued[holder] = returnAmount;\n }\n }\n }\n\n /**\n * @notice Update and distribute tokens\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function updateAndDistributeRewardsInternal(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers\n ) internal {\n uint256 j;\n uint256 holdersLength = holders.length;\n uint256 vTokensLength = vTokens.length;\n\n for (uint256 i; i < vTokensLength; ++i) {\n VToken vToken = vTokens[i];\n ensureListed(markets[address(vToken)]);\n if (borrowers) {\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n for (j = 0; j < holdersLength; ++j) {\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\n }\n }\n\n if (suppliers) {\n updateVenusSupplyIndex(address(vToken));\n for (j = 0; j < holdersLength; ++j) {\n distributeSupplierVenus(address(vToken), holders[j]);\n }\n }\n }\n }\n\n /**\n * @notice Returns the XVS vToken address\n * @return The address of XVS vToken\n */\n function getXVSVTokenAddress() external view returns (address) {\n return xvsVToken;\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/SetterFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { ComptrollerLensInterfaceR1 } from \"../../ComptrollerLensInterfaceR1.sol\";\nimport { VAIControllerInterface } from \"../../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { IPrime } from \"../../../../Tokens/Prime/IPrime.sol\";\nimport { ISetterFacetR1 } from \"../interfaces/ISetterFacetR1.sol\";\nimport { FacetBaseR1 } from \"./FacetBaseR1.sol\";\n\n/**\n * @title SetterFacet\n * @author Venus\n * @dev This facet contains all the setters for the states\n * @notice This facet contract contains all the configurational setter functions\n */\ncontract SetterFacetR1 is ISetterFacetR1, FacetBaseR1 {\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor is changed by admin\n event NewCollateralFactor(\n VToken indexed vToken,\n uint256 oldCollateralFactorMantissa,\n uint256 newCollateralFactorMantissa\n );\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when VAIController is changed\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\n\n /// @notice Emitted when VAI mint rate is changed by admin\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\n\n /// @notice Emitted when protocol state is changed by admin\n event ActionProtocolPaused(bool state);\n\n /// @notice Emitted when treasury guardian is changed\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\n\n /// @notice Emitted when treasury address is changed\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\n\n /// @notice Emitted when treasury percent is changed\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\n\n /// @notice Emitted when liquidator adress is changed\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\n\n /// @notice Emitted when ComptrollerLens address is changed\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\n\n /// @notice Emitted when pause guardian is changed\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\n\n /// @notice Emitted when VAI Vault info is changed\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\n\n /// @notice Emitted when Venus VAI Vault rate is changed\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\n\n /// @notice Emitted when prime token contract address is changed\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for all users in a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\n event IsForcedLiquidationEnabledForUserUpdated(address indexed borrower, address indexed vToken, bool enable);\n\n /// @notice Emitted when XVS token address is changed\n event NewXVSToken(address indexed oldXVS, address indexed newXVS);\n\n /// @notice Emitted when XVS vToken address is changed\n event NewXVSVToken(address indexed oldXVSVToken, address indexed newXVSVToken);\n\n /**\n * @notice Compare two addresses to ensure they are different\n * @param oldAddress The original address to compare\n * @param newAddress The new address to compare\n */\n modifier compareAddress(address oldAddress, address newAddress) {\n require(oldAddress != newAddress, \"old address is same as new address\");\n _;\n }\n\n /**\n * @notice Compare two values to ensure they are different\n * @param oldValue The original value to compare\n * @param newValue The new value to compare\n */\n modifier compareValue(uint256 oldValue, uint256 newValue) {\n require(oldValue != newValue, \"old value is same as new value\");\n _;\n }\n\n /**\n * @notice Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\n * @param newOracle The new price oracle to set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\n return __setPriceOracle(newOracle);\n }\n\n /**\n * @notice Sets a new price oracle for the comptroller\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\n * @param newOracle The new price oracle to set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\n return __setPriceOracle(newOracle);\n }\n\n /**\n * @notice Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\n return __setCloseFactor(newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the closeFactor used when liquidating borrows\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\n return __setCloseFactor(newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Allows the contract admin to set the address of access control of this contract\n * @param newAccessControlAddress New address for the access control\n * @return uint256 0=success, otherwise will revert\n */\n function _setAccessControl(\n address newAccessControlAddress\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newAccessControlAddress);\n\n address oldAccessControlAddress = accessControl;\n\n accessControl = newAccessControlAddress;\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _setCollateralFactor to support the Isolated Lending Comptroller Interface\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256) {\n require(\n newCollateralFactorMantissa == newLiquidationThresholdMantissa,\n \"collateral factor and liquidation threshold must be the same\"\n );\n return __setCollateralFactor(vToken, newCollateralFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev Allows a privileged role to set the collateralFactorMantissa\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function _setCollateralFactor(VToken vToken, uint256 newCollateralFactorMantissa) external returns (uint256) {\n return __setCollateralFactor(vToken, newCollateralFactorMantissa);\n }\n\n /**\n * @notice Alias to _setLiquidationIncentive to support the Isolated Lending Comptroller Interface\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256) {\n return __setLiquidationIncentive(newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev Allows a privileged role to set the liquidationIncentiveMantissa\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function _setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256) {\n return __setLiquidationIncentive(newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Update the address of the liquidator contract\n * @dev Allows the contract admin to update the address of liquidator contract\n * @param newLiquidatorContract_ The new address of the liquidator contract\n */\n function _setLiquidatorContract(\n address newLiquidatorContract_\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newLiquidatorContract_);\n address oldLiquidatorContract = liquidatorContract;\n liquidatorContract = newLiquidatorContract_;\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\n }\n\n /**\n * @notice Admin function to change the Pause Guardian\n * @dev Allows the contract admin to change the Pause Guardian\n * @param newPauseGuardian The address of the new Pause Guardian\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _setPauseGuardian(\n address newPauseGuardian\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(newPauseGuardian);\n\n // Save current value for inclusion in log\n address oldPauseGuardian = pauseGuardian;\n // Store pauseGuardian with value newPauseGuardian\n pauseGuardian = newPauseGuardian;\n\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\n */\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\n }\n\n /**\n * @notice Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\n }\n\n /**\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\n }\n\n /**\n * @notice Set whole protocol pause/unpause state\n * @dev Allows a privileged role to pause/unpause protocol\n * @param state The new state (true=paused, false=unpaused)\n * @return bool The updated state of the protocol\n */\n function _setProtocolPaused(bool state) external returns (bool) {\n ensureAllowed(\"_setProtocolPaused(bool)\");\n\n protocolPaused = state;\n emit ActionProtocolPaused(state);\n return state;\n }\n\n /**\n * @notice Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n __setActionsPaused(markets_, actions_, paused_);\n }\n\n /**\n * @notice Pause/unpause certain actions\n * @dev Allows a privileged role to pause/unpause the protocol action state\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n __setActionsPaused(markets_, actions_, paused_);\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function setActionPausedInternal(address market, Action action, bool paused) internal {\n ensureListed(markets[market]);\n _actionPaused[market][uint256(action)] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @notice Sets a new VAI controller\n * @dev Admin function to set a new VAI controller\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIController(\n VAIControllerInterface vaiController_\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(vaiController_));\n\n VAIControllerInterface oldVaiController = vaiController;\n vaiController = vaiController_;\n emit NewVAIController(oldVaiController, vaiController_);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the VAI mint rate\n * @param newVAIMintRate The new VAI mint rate to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIMintRate(\n uint256 newVAIMintRate\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n uint256 oldVAIMintRate = vaiMintRate;\n vaiMintRate = newVAIMintRate;\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the minted VAI amount of the `owner`\n * @param owner The address of the account to set\n * @param amount The amount of VAI to set to the account\n * @return The number of minted VAI by `owner`\n */\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\n checkProtocolPauseState();\n\n // Pausing is a very serious situation - we revert to sound the alarms\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \"VAI is paused\");\n // Check caller is vaiController\n if (msg.sender != address(vaiController)) {\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\n }\n mintedVAIs[owner] = amount;\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the treasury data.\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\n * @param newTreasuryAddress The new address of the treasury to be set\n * @param newTreasuryPercent The new treasury percent to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256) {\n // Check caller is admin\n ensureAdminOr(treasuryGuardian);\n\n require(newTreasuryPercent < 1e18, \"percent >= 100%\");\n ensureNonzeroAddress(newTreasuryGuardian);\n ensureNonzeroAddress(newTreasuryAddress);\n\n address oldTreasuryGuardian = treasuryGuardian;\n address oldTreasuryAddress = treasuryAddress;\n uint256 oldTreasuryPercent = treasuryPercent;\n\n treasuryGuardian = newTreasuryGuardian;\n treasuryAddress = newTreasuryAddress;\n treasuryPercent = newTreasuryPercent;\n\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\n\n return uint256(Error.NO_ERROR);\n }\n\n /*** Venus Distribution ***/\n\n /**\n * @dev Set ComptrollerLens contract address\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptrollerLens(\n ComptrollerLensInterfaceR1 comptrollerLens_\n ) external virtual compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the amount of XVS distributed per block to VAI Vault\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\n */\n function _setVenusVAIVaultRate(\n uint256 venusVAIVaultRate_\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\n ensureAdmin();\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\n venusVAIVaultRate = venusVAIVaultRate_;\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\n }\n\n /**\n * @notice Set the VAI Vault infos\n * @param vault_ The address of the VAI Vault\n * @param releaseStartBlock_ The start block of release to VAI Vault\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\n */\n function _setVAIVaultInfo(\n address vault_,\n uint256 releaseStartBlock_,\n uint256 minReleaseAmount_\n ) external compareAddress(vaiVaultAddress, vault_) {\n ensureAdmin();\n ensureNonzeroAddress(vault_);\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n\n vaiVaultAddress = vault_;\n releaseStartBlock = releaseStartBlock_;\n minReleaseAmount = minReleaseAmount_;\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\n }\n\n /**\n * @notice Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\n * @param _prime The new prime token contract to be set\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function setPrimeToken(IPrime _prime) external returns (uint256) {\n return __setPrimeToken(_prime);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime The new prime token contract to be set\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPrimeToken(IPrime _prime) external returns (uint256) {\n return __setPrimeToken(_prime);\n }\n\n /**\n * @notice Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n __setForcedLiquidation(vTokenBorrowed, enable);\n }\n\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\n * borrows in the market may be liquidated regardless of the account liquidity\n * @dev Allows a privileged role to set enable/disable forced liquidations\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n __setForcedLiquidation(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Enables forced liquidations for user's borrows in a certain market. If forced\n * liquidation is enabled, user's borrows in the market may be liquidated regardless of\n * the account liquidity. Forced liquidation may be enabled for a user even if it is not\n * enabled for the entire market.\n * @param borrower The address of the borrower\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external {\n ensureAllowed(\"_setForcedLiquidationForUser(address,address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n }\n isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledForUserUpdated(borrower, vTokenBorrowed, enable);\n }\n\n /**\n * @notice Set the address of the XVS token\n * @param xvs_ The address of the XVS token\n */\n function _setXVSToken(address xvs_) external {\n ensureAdmin();\n ensureNonzeroAddress(xvs_);\n\n emit NewXVSToken(xvs, xvs_);\n xvs = xvs_;\n }\n\n /**\n * @notice Set the address of the XVS vToken\n * @param xvsVToken_ The address of the XVS vToken\n */\n function _setXVSVToken(address xvsVToken_) external {\n ensureAdmin();\n ensureNonzeroAddress(xvsVToken_);\n\n address underlying = VToken(xvsVToken_).underlying();\n require(underlying == xvs, \"invalid xvs vtoken address\");\n\n emit NewXVSVToken(xvsVToken, xvsVToken_);\n xvsVToken = xvsVToken_;\n }\n\n /**\n * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle\n * @param newOracle The new price oracle to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setPriceOracle(\n ResilientOracleInterface newOracle\n ) internal compareAddress(address(oracle), address(newOracle)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(newOracle));\n\n // Track the old oracle for the comptroller\n ResilientOracleInterface oldOracle = oracle;\n\n // Set comptroller's oracle to newOracle\n oracle = newOracle;\n\n // Emit NewPriceOracle(oldOracle, newOracle)\n emit NewPriceOracle(oldOracle, newOracle);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the close factor. Used by _setCloseFactor and setCloseFactor\n * @param newCloseFactorMantissa The new close factor to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setCloseFactor(\n uint256 newCloseFactorMantissa\n ) internal compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\n\n //-- Check close factor <= 0.9\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\n //-- Check close factor >= 0.05\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\n\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\n }\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the collateral factor. Used by _setCollateralFactor and setCollateralFactor\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa\n )\n internal\n compareValue(markets[address(vToken)].collateralFactorMantissa, newCollateralFactorMantissa)\n returns (uint256)\n {\n // Check caller is allowed by access control manager\n ensureAllowed(\"_setCollateralFactor(address,uint256)\");\n ensureNonzeroAddress(address(vToken));\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n ensureListed(market);\n\n Exp memory newCollateralFactorExp = Exp({ mantissa: newCollateralFactorMantissa });\n\n //-- Check collateral factor <= 0.9\n Exp memory highLimit = Exp({ mantissa: collateralFactorMaxMantissa });\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\n }\n\n // Set market's collateral factor to new collateral factor, remember old value\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n\n // Emit event with asset, old collateral factor, and new collateral factor\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the liquidation incentive. Used by _setLiquidationIncentive and setLiquidationIncentive\n * @param newLiquidationIncentiveMantissa The new liquidation incentive to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setLiquidationIncentive(\n uint256 newLiquidationIncentiveMantissa\n ) internal compareValue(liquidationIncentiveMantissa, newLiquidationIncentiveMantissa) returns (uint256) {\n ensureAllowed(\"_setLiquidationIncentive(uint256)\");\n\n require(newLiquidationIncentiveMantissa >= 1e18, \"incentive < 1e18\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the borrow caps. Used by _setMarketBorrowCaps and setMarketBorrowCaps\n * @param vTokens The markets to set the borrow caps on\n * @param newBorrowCaps The new borrow caps to be set\n */\n function __setMarketBorrowCaps(VToken[] memory vTokens, uint256[] memory newBorrowCaps) internal {\n ensureAllowed(\"_setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @dev Updates the supply caps. Used by _setMarketSupplyCaps and setMarketSupplyCaps\n * @param vTokens The markets to set the supply caps on\n * @param newSupplyCaps The new supply caps to be set\n */\n function __setMarketSupplyCaps(VToken[] memory vTokens, uint256[] memory newSupplyCaps) internal {\n ensureAllowed(\"_setMarketSupplyCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numSupplyCaps = newSupplyCaps.length;\n\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @dev Updates the prime token. Used by _setPrimeToken and setPrimeToken\n * @param _prime The new prime token to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setPrimeToken(IPrime _prime) internal returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(_prime));\n\n IPrime oldPrime = prime;\n prime = _prime;\n emit NewPrimeToken(oldPrime, _prime);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the forced liquidation. Used by _setForcedLiquidation and setForcedLiquidation\n * @param vTokenBorrowed The market to set the forced liquidation on\n * @param enable Whether to enable forced liquidations\n */\n function __setForcedLiquidation(address vTokenBorrowed, bool enable) internal {\n ensureAllowed(\"_setForcedLiquidation(address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n }\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @dev Updates the actions paused. Used by _setActionsPaused and setActionsPaused\n * @param markets_ The markets to set the actions paused on\n * @param actions_ The actions to set the paused state on\n * @param paused_ The new paused state to be set\n */\n function __setActionsPaused(address[] memory markets_, Action[] memory actions_, bool paused_) internal {\n ensureAllowed(\"_setActionsPaused(address[],uint8[],bool)\");\n\n uint256 numMarkets = markets_.length;\n uint256 numActions = actions_.length;\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/XVSRewardsHelperR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { FacetBaseR1 } from \"./FacetBaseR1.sol\";\n\n/**\n * @title XVSRewardsHelper\n * @author Venus\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\n */\ncontract XVSRewardsHelperR1 is FacetBaseR1 {\n /// @notice Emitted when XVS is distributed to a borrower\n event DistributedBorrowerVenus(\n VToken indexed vToken,\n address indexed borrower,\n uint256 venusDelta,\n uint256 venusBorrowIndex\n );\n\n /// @notice Emitted when XVS is distributed to a supplier\n event DistributedSupplierVenus(\n VToken indexed vToken,\n address indexed supplier,\n uint256 venusDelta,\n uint256 venusSupplyIndex\n );\n\n /**\n * @notice Accrue XVS to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n */\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\n if (deltaBlocks != 0 && borrowSpeed != 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \"224\");\n borrowState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n borrowState.block = blockNumber;\n }\n }\n\n /**\n * @notice Accrue XVS to the market by updating the supply index\n * @param vToken The market whose supply index to update\n */\n function updateVenusSupplyIndex(address vToken) internal {\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n uint256 supplySpeed = venusSupplySpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\n if (deltaBlocks != 0 && supplySpeed != 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \"224\");\n supplyState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n supplyState.block = blockNumber;\n }\n }\n\n /**\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute XVS to\n */\n function distributeSupplierVenus(address vToken, address supplier) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 supplyIndex = venusSupplyState[vToken].index;\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\n // Update supplier's index to the current index since we are distributing accrued XVS\n venusSupplierIndex[vToken][supplier] = supplyIndex;\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n // Multiply of supplierTokens and supplierDelta\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\n // Addition of supplierAccrued and supplierDelta\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\n }\n\n /**\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute XVS to\n */\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 borrowIndex = venusBorrowState[vToken].index;\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\n // Update borrowers's index to the current index since we are distributing accrued XVS\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/IDiamondCutR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\ninterface IDiamondCutR1 {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n function diamondCut(FacetCut[] calldata _diamondCut) external;\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/IMarketFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\n\ninterface IMarketFacetR1 {\n function isComptroller() external pure returns (bool);\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function checkMembership(address account, VToken vToken) external view returns (bool);\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n function _supportMarket(VToken vToken) external returns (uint256);\n\n function supportMarket(VToken vToken) external returns (uint256);\n\n function isMarketListed(VToken vToken) external view returns (bool);\n\n function getAssetsIn(address account) external view returns (VToken[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function updateDelegate(address delegate, bool allowBorrows) external;\n\n function unlistMarket(address market) external returns (uint256);\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/IPolicyFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\n\ninterface IPolicyFacetR1 {\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\n\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\n\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\n\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount\n ) external returns (uint256);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount,\n uint256 borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount,\n uint256 seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external returns (uint256);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external;\n\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256);\n\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\n\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256);\n\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external;\n\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall);\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/IRewardFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\n\ninterface IRewardFacetR1 {\n function claimVenus(address holder) external;\n\n function claimVenus(address holder, VToken[] calldata vTokens) external;\n\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\n\n function claimVenusAsCollateral(address holder) external;\n\n function _grantXVS(address recipient, uint256 amount) external;\n\n function getXVSVTokenAddress() external view returns (address);\n\n function claimVenus(\n address[] calldata holders,\n VToken[] calldata vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) external;\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256);\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/ISetterFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { VAIControllerInterface } from \"../../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterfaceR1 } from \"../../ComptrollerLensInterfaceR1.sol\";\nimport { IPrime } from \"../../../../Tokens/Prime/IPrime.sol\";\n\ninterface ISetterFacetR1 {\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\n\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\n\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\n\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256);\n\n function _setCollateralFactor(VToken vToken, uint256 newCollateralFactorMantissa) external returns (uint256);\n\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256);\n\n function _setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256);\n\n function _setLiquidatorContract(address newLiquidatorContract_) external;\n\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\n\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setProtocolPaused(bool state) external returns (bool);\n\n function setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\n\n function _setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\n\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\n\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\n\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\n\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256);\n\n function _setComptrollerLens(ComptrollerLensInterfaceR1 comptrollerLens_) external returns (uint256);\n\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\n\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\n\n function _setForcedLiquidation(address vToken, bool enable) external;\n\n function setPrimeToken(IPrime _prime) external returns (uint256);\n\n function _setPrimeToken(IPrime _prime) external returns (uint);\n\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external;\n\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external;\n\n function _setXVSToken(address xvs_) external;\n\n function _setXVSVToken(address xvsVToken_) external;\n}\n" + }, + "contracts/Comptroller/Types/PoolMarketId.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\n/// @notice Strongly-typed identifier for pool markets mapping keys\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\ntype PoolMarketId is bytes32;\n\n " + }, + "contracts/Comptroller/Unitroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { UnitrollerAdminStorage } from \"./ComptrollerStorage.sol\";\nimport { ComptrollerErrorReporter } from \"../Utils/ErrorReporter.sol\";\n\n/**\n * @title ComptrollerCore\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\n * VTokens should reference this contract as their comptroller.\n */\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\n /**\n * @notice Emitted when pendingComptrollerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor() {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public returns (uint) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldImplementation = comptrollerImplementation;\n address oldPendingImplementation = pendingComptrollerImplementation;\n\n comptrollerImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = address(0);\n\n emit NewImplementation(oldImplementation, comptrollerImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\n // Check caller = admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n }\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n fallback() external {\n // delegate all other functions to current implementation\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/external/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\ninterface IProtocolShareReserve {\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\n}\n" + }, + "contracts/external/IWBNB.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\ninterface IWBNB is IERC20Upgradeable {\n function deposit() external payable;\n}\n" + }, + "contracts/FlashLoan/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../Tokens/VTokens/VToken.sol\";\n\n/// @title IFlashLoanReceiver\n/// @notice Interface for flashLoan receiver contract, which executes custom logic with flash-borrowed assets.\n/// @dev This interface defines the method that must be implemented by any contract wishing to interact with the flashLoan system.\n/// Contracts must ensure they have the means to repay at least the premium (fee), with any unpaid balance becoming debt.\ninterface IFlashLoanReceiver {\n /**\n * @notice Executes an operation after receiving the flash-borrowed assets.\n * @dev Implementation of this function must ensure at least the premium (fee) is repaid within the same transaction.\n * Any unpaid balance (principal + premium - repaid amount) will be added to the onBehalf address's borrow balance.\n * @param vTokens The vToken contracts corresponding to the flash-borrowed underlying assets.\n * @param amounts The amounts of each underlying asset that were flash-borrowed.\n * @param premiums The premiums (fees) associated with each flash-borrowed asset.\n * @param initiator The address that initiated the flash loan.\n * @param onBehalf The address of the user whose debt position will be used for any unpaid flash loan balance.\n * @param param Additional parameters encoded as bytes. These can be used to pass custom data to the receiver contract.\n * @return success True if the operation succeeds (regardless of repayment amount), false if the operation fails.\n * @return repayAmounts Array of uint256 representing the amounts to be repaid for each asset. The receiver contract\n * must approve these amounts to the respective vToken contracts before this function returns.\n */\n function executeOperation(\n VToken[] calldata vTokens,\n uint256[] calldata amounts,\n uint256[] calldata premiums,\n address initiator,\n address onBehalf,\n bytes calldata param\n ) external returns (bool success, uint256[] memory repayAmounts);\n}\n" + }, + "contracts/InterestRateModels/InterestRateModelV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Venus's InterestRateModelV8 Interface\n * @author Venus\n */\nabstract contract InterestRateModelV8 {\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\n bool public constant isInterestRateModel = true;\n\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amnount of reserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amnount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa\n ) external view virtual returns (uint256);\n}\n" + }, + "contracts/InterfacesV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\ninterface IVToken is IERC20Upgradeable {\n function accrueInterest() external returns (uint256);\n\n function redeem(uint256 redeemTokens) external returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256);\n\n function borrowBalanceCurrent(address borrower) external returns (uint256);\n\n function balanceOfUnderlying(address owner) external returns (uint256);\n\n function comptroller() external view returns (IComptroller);\n\n function borrowBalanceStored(address account) external view returns (uint256);\n}\n\ninterface IVBep20 is IVToken {\n function borrowBehalf(address borrower, uint256 borrowAmount) external returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n IVToken vTokenCollateral\n ) external returns (uint256);\n\n function underlying() external view returns (address);\n}\n\ninterface IVBNB is IVToken {\n function repayBorrowBehalf(address borrower) external payable;\n\n function liquidateBorrow(address borrower, IVToken vTokenCollateral) external payable;\n}\n\ninterface IVAIController {\n function accrueVAIInterest() external;\n\n function liquidateVAI(\n address borrower,\n uint256 repayAmount,\n IVToken vTokenCollateral\n ) external returns (uint256, uint256);\n\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\n\n function getVAIAddress() external view returns (address);\n\n function getVAIRepayAmount(address borrower) external view returns (uint256);\n}\n\ninterface IComptroller {\n enum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n }\n\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external;\n\n function vaiController() external view returns (IVAIController);\n\n function liquidatorContract() external view returns (address);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function actionPaused(address market, Action action) external view returns (bool);\n\n function markets(address) external view returns (bool, uint256, bool);\n\n function isForcedLiquidationEnabled(address) external view returns (bool);\n\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\n}\n\ninterface ILiquidator {\n function restrictLiquidation(address borrower) external;\n\n function unrestrictLiquidation(address borrower) external;\n\n function addToAllowlist(address borrower, address liquidator) external;\n\n function removeFromAllowlist(address borrower, address liquidator) external;\n\n function liquidateBorrow(\n address vToken,\n address borrower,\n uint256 repayAmount,\n IVToken vTokenCollateral\n ) external payable;\n\n function setTreasuryPercent(uint256 newTreasuryPercentMantissa) external;\n\n function treasuryPercentMantissa() external view returns (uint256);\n}\n" + }, + "contracts/Lens/ComptrollerLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { ExponentialNoError } from \"../Utils/ExponentialNoError.sol\";\nimport { ComptrollerErrorReporter } from \"../Utils/ErrorReporter.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { ComptrollerLensInterface } from \"../Comptroller/ComptrollerLensInterface.sol\";\nimport { VAIControllerInterface } from \"../Tokens/VAI/VAIControllerInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\nimport { WeightFunction } from \"../Comptroller/Diamond/interfaces/IFacetBase.sol\";\n\n/**\n * @title ComptrollerLens Contract\n * @author Venus\n * @notice The ComptrollerLens contract has functions to get the number of tokens that\n * can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\n */\ncontract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, ExponentialNoError {\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountLiquidityLocalVars {\n uint sumCollateral;\n uint sumBorrowPlusEffects;\n uint vTokenBalance;\n uint borrowBalance;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp weightedFactor;\n Exp exchangeRate;\n Exp tokensToDenom;\n Exp collateralPrice;\n Exp debtPrice;\n IDeviationBoundedOracle boundedOracle;\n ResilientOracleInterface spotOracle;\n }\n\n /**\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\n * @dev This will be used only in vBNB\n * @param comptroller Address of comptroller\n * @param vTokenBorrowed Address of the borrowed vToken\n * @param vTokenCollateral Address of collateral for the borrow\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\n * @return A tuple of error code, and tokens to seize\n */\n function liquidateCalculateSeizeTokens(\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\n\n uint seizeTokens = _calculateSeizeTokens(\n actualRepayAmount,\n liquidationIncentiveMantissa,\n priceBorrowedMantissa,\n priceCollateralMantissa,\n exchangeRateMantissa\n );\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /**\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\n * @param borrower Address of borrower whose collateral is being seized\n * @param comptroller Address of comptroller\n * @param vTokenBorrowed Address of the borrowed vToken\n * @param vTokenCollateral Address of collateral for the borrow\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\n * @return A tuple of error code, and tokens to seize\n */\n function liquidateCalculateSeizeTokens(\n address borrower,\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getEffectiveLiquidationIncentive(\n borrower,\n vTokenCollateral\n );\n\n uint seizeTokens = _calculateSeizeTokens(\n actualRepayAmount,\n liquidationIncentiveMantissa,\n priceBorrowedMantissa,\n priceCollateralMantissa,\n exchangeRateMantissa\n );\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /**\n * @notice Computes the number of VAI tokens to be seized in a liquidation event\n * @param comptroller Address of comptroller\n * @param vTokenCollateral Address of collateral for vToken\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of the total borrowed amount\n * @return A tuple of error code, and tokens to seize\n */\n function liquidateVAICalculateSeizeTokens(\n address comptroller,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa = 1e18; // Note: this is VAI\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\n if (priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\n uint seizeTokens = _calculateSeizeTokens(\n actualRepayAmount,\n liquidationIncentiveMantissa,\n priceBorrowedMantissa,\n priceCollateralMantissa,\n exchangeRateMantissa\n );\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /**\n * @notice Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow\n * A snapshot of the account is taken and the total borrow amount of the account is calculated\n * @param comptroller Address of comptroller\n * @param account Address of the borrowed vToken\n * @param vTokenModify Address of collateral for vToken\n * @param redeemTokens Number of vTokens being redeemed\n * @param borrowAmount Amount borrowed\n * @param weightingStrategy The weighting strategy to use:\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\n * @return Returns a tuple of error code, liquidity, and shortfall\n */\n function getHypotheticalAccountLiquidity(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount,\n WeightFunction weightingStrategy\n ) external view returns (uint, uint, uint) {\n (uint errorCode, AccountLiquidityLocalVars memory vars) = _calculateAccountPosition(\n comptroller,\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount,\n weightingStrategy\n );\n if (errorCode != 0) {\n return (errorCode, 0, 0);\n }\n\n // These are safe, as the underflow condition is checked first\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\n return (uint(Error.NO_ERROR), vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\n } else {\n return (uint(Error.NO_ERROR), 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\n }\n }\n\n /**\n * @notice Computes an account's aggregate weighted-collateral and total-borrow values,\n * optionally applying hypothetical redeem/borrow effects on a single market.\n * @dev Pricing differs by weighting strategy:\n * - USE_COLLATERAL_FACTOR: collateral is valued at `DeviationBoundedOracle.getBoundedCollateralPriceView`,\n * borrows at `getBoundedDebtPriceView`.\n * - USE_LIQUIDATION_THRESHOLD: both collateral and borrows use the spot oracle price.\n * VAI borrows (from `vaiController.getVAIRepayAmount`) are added to `sumBorrowPlusEffects` after\n * the per-asset loop, regardless of weighting strategy.\n * @param comptroller Address of the comptroller whose markets and oracle are used\n * @param account Address of the account whose position is being computed\n * @param vTokenModify Market to apply hypothetical effects on; pass `VToken(address(0))` for none\n * @param redeemTokens Number of vTokens hypothetically redeemed from `vTokenModify`\n * @param borrowAmount Amount of underlying hypothetically borrowed from `vTokenModify`\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\n * @return oErr 0 on success, or a non-zero `Error` code (SNAPSHOT_ERROR or PRICE_ERROR) on failure\n * @return vars Accumulated position data; `sumCollateral` and `sumBorrowPlusEffects` are the primary outputs\n */\n function _calculateAccountPosition(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount,\n WeightFunction weightingStrategy\n ) internal view returns (uint oErr, AccountLiquidityLocalVars memory vars) {\n // For each asset the account is in\n VToken[] memory assets = ComptrollerInterface(comptroller).getAssetsIn(account);\n uint assetsCount = assets.length;\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\n vars.boundedOracle = ComptrollerInterface(comptroller).deviationBoundedOracle();\n } else {\n vars.spotOracle = ComptrollerInterface(comptroller).oracle();\n }\n for (uint i = 0; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(\n account\n );\n if (oErr != 0) {\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\n return (uint(Error.SNAPSHOT_ERROR), vars);\n }\n vars.weightedFactor = Exp({\n mantissa: ComptrollerInterface(comptroller).getEffectiveLtvFactor(\n account,\n address(asset),\n weightingStrategy\n )\n });\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n // Determine bounded prices for CF path\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\n (uint256 collateralPriceMantissa, uint256 debtPriceMantissa) = vars.boundedOracle.getBoundedPricesView(\n address(asset)\n );\n if (collateralPriceMantissa == 0 || debtPriceMantissa == 0) {\n return (uint(Error.PRICE_ERROR), vars);\n }\n vars.collateralPrice = Exp({ mantissa: collateralPriceMantissa });\n vars.debtPrice = Exp({ mantissa: debtPriceMantissa });\n } else {\n // LT path — always spot\n vars.oraclePriceMantissa = vars.spotOracle.getUnderlyingPrice(address(asset));\n if (vars.oraclePriceMantissa == 0) {\n return (uint(Error.PRICE_ERROR), vars);\n }\n vars.collateralPrice = Exp({ mantissa: vars.oraclePriceMantissa });\n vars.debtPrice = Exp({ mantissa: vars.oraclePriceMantissa });\n }\n\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\n vars.tokensToDenom = mul_(mul_(vars.weightedFactor, vars.exchangeRate), vars.collateralPrice);\n\n // sumCollateral += tokensToDenom * vTokenBalance\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.vTokenBalance, vars.sumCollateral);\n\n // sumBorrowPlusEffects += debtPrice * borrowBalance\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.debtPrice,\n vars.borrowBalance,\n vars.sumBorrowPlusEffects\n );\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect — uses collateral-bounded tokensToDenom\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.tokensToDenom,\n redeemTokens,\n vars.sumBorrowPlusEffects\n );\n\n // borrow effect — uses debt-bounded price\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.debtPrice,\n borrowAmount,\n vars.sumBorrowPlusEffects\n );\n }\n }\n\n VAIControllerInterface vaiController = ComptrollerInterface(comptroller).vaiController();\n\n if (address(vaiController) != address(0)) {\n vars.sumBorrowPlusEffects = add_(vars.sumBorrowPlusEffects, vaiController.getVAIRepayAmount(account));\n }\n oErr = uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Calculate the number of tokens to seize during liquidation\n * @param actualRepayAmount The amount of debt being repaid in the liquidation\n * @param liquidationIncentiveMantissa The liquidation incentive, scaled by 1e18\n * @param priceBorrowedMantissa The price of the borrowed asset, scaled by 1e18\n * @param priceCollateralMantissa The price of the collateral asset, scaled by 1e18\n * @param exchangeRateMantissa The exchange rate of the collateral asset, scaled by 1e18\n * @return seizeTokens The number of tokens to seize during liquidation, scaled by 1e18\n */\n function _calculateSeizeTokens(\n uint actualRepayAmount,\n uint liquidationIncentiveMantissa,\n uint priceBorrowedMantissa,\n uint priceCollateralMantissa,\n uint exchangeRateMantissa\n ) internal pure returns (uint seizeTokens) {\n Exp memory numerator = mul_(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n Exp({ mantissa: priceBorrowedMantissa })\n );\n Exp memory denominator = mul_(\n Exp({ mantissa: priceCollateralMantissa }),\n Exp({ mantissa: exchangeRateMantissa })\n );\n\n seizeTokens = mul_ScalarTruncate(div_(numerator, denominator), actualRepayAmount);\n }\n}\n" + }, + "contracts/Lens/SnapshotLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { ExponentialNoError } from \"../Utils/ExponentialNoError.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VBep20 } from \"../Tokens/VTokens/VBep20.sol\";\nimport { WeightFunction } from \"../Comptroller/Diamond/interfaces/IFacetBase.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\n\ncontract SnapshotLens is ExponentialNoError {\n struct AccountSnapshot {\n address account;\n string assetName;\n address vTokenAddress;\n address underlyingAssetAddress;\n uint256 supply;\n uint256 supplyInUsd;\n uint256 collateral;\n uint256 borrows;\n uint256 borrowsInUsd;\n uint256 spotPrice;\n uint256 boundedCollateralPrice;\n uint256 boundedDebtPrice;\n uint256 accruedInterest;\n uint vTokenDecimals;\n uint underlyingDecimals;\n uint exchangeRate;\n bool isACollateral;\n }\n\n /** Snapshot calculation **/\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account snapshot.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountSnapshotLocalVars {\n uint collateral;\n uint vTokenBalance;\n uint borrowBalance;\n uint borrowsInUsd;\n uint balanceOfUnderlying;\n uint supplyInUsd;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp collateralFactor;\n Exp exchangeRate;\n Exp oraclePrice;\n Exp tokensToDenom;\n bool isACollateral;\n }\n\n function getAccountSnapshot(\n address payable account,\n address comptrollerAddress\n ) public returns (AccountSnapshot[] memory) {\n // For each asset the account is in\n VToken[] memory assets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n AccountSnapshot[] memory accountSnapshots = new AccountSnapshot[](assets.length);\n for (uint256 i = 0; i < assets.length; ++i) {\n accountSnapshots[i] = getAccountSnapshot(account, comptrollerAddress, assets[i]);\n }\n return accountSnapshots;\n }\n\n function isACollateral(address account, address asset, address comptrollerAddress) public view returns (bool) {\n VToken[] memory assetsAsCollateral = ComptrollerInterface(comptrollerAddress).getAssetsIn(account);\n for (uint256 j = 0; j < assetsAsCollateral.length; ++j) {\n if (address(assetsAsCollateral[j]) == asset) {\n return true;\n }\n }\n\n return false;\n }\n\n function getAccountSnapshot(\n address payable account,\n address comptrollerAddress,\n VToken vToken\n ) public returns (AccountSnapshot memory) {\n AccountSnapshotLocalVars memory vars; // Holds all our calculation results\n uint oErr;\n\n // Read the balances and exchange rate from the vToken\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = vToken.getAccountSnapshot(account);\n require(oErr == 0, \"Snapshot Error\");\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n uint collateralFactorMantissa = ComptrollerInterface(comptrollerAddress).getEffectiveLtvFactor(\n account,\n address(vToken),\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n vars.collateralFactor = Exp({ mantissa: collateralFactorMantissa });\n\n // Get the normalized spot price of the asset\n vars.oraclePriceMantissa = ComptrollerInterface(comptrollerAddress).oracle().getUnderlyingPrice(\n address(vToken)\n );\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\n\n // Get bounded prices from DBO (used in CF-path liquidity calculations)\n IDeviationBoundedOracle boundedOracle = ComptrollerInterface(comptrollerAddress).deviationBoundedOracle();\n (uint256 boundedCollateralPriceMantissa, uint256 boundedDebtPriceMantissa) = boundedOracle.getBoundedPricesView(\n address(vToken)\n );\n\n // Collateral uses bounded collateral price (mirrors ComptrollerLens CF path)\n Exp memory collateralPrice = Exp({ mantissa: boundedCollateralPriceMantissa });\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), collateralPrice);\n vars.collateral = mul_ScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\n\n // Supply in USD uses spot price (real market value of supplied assets)\n vars.balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n vars.supplyInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.balanceOfUnderlying);\n\n // Borrows in USD uses bounded debt price (mirrors ComptrollerLens CF path)\n Exp memory debtPrice = Exp({ mantissa: boundedDebtPriceMantissa });\n vars.borrowsInUsd = mul_ScalarTruncate(debtPrice, vars.borrowBalance);\n\n address underlyingAssetAddress;\n uint underlyingDecimals;\n\n if (compareStrings(vToken.symbol(), \"vBNB\")) {\n underlyingAssetAddress = address(0);\n underlyingDecimals = 18;\n } else {\n VBep20 vBep20 = VBep20(address(vToken));\n underlyingAssetAddress = vBep20.underlying();\n underlyingDecimals = IERC20Metadata(vBep20.underlying()).decimals();\n }\n\n vars.isACollateral = isACollateral(account, address(vToken), comptrollerAddress);\n\n return\n AccountSnapshot({\n account: account,\n assetName: vToken.name(),\n vTokenAddress: address(vToken),\n underlyingAssetAddress: underlyingAssetAddress,\n supply: vars.balanceOfUnderlying,\n supplyInUsd: vars.supplyInUsd,\n collateral: vars.collateral,\n borrows: vars.borrowBalance,\n borrowsInUsd: vars.borrowsInUsd,\n spotPrice: vars.oraclePriceMantissa,\n boundedCollateralPrice: boundedCollateralPriceMantissa,\n boundedDebtPrice: boundedDebtPriceMantissa,\n accruedInterest: vToken.borrowIndex(),\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n exchangeRate: vToken.exchangeRateCurrent(),\n isACollateral: vars.isACollateral\n });\n }\n\n // utilities\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}\n" + }, + "contracts/Lens/VenusLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { ExponentialNoError } from \"../Utils/ExponentialNoError.sol\";\nimport { VBep20 } from \"../Tokens/VTokens/VBep20.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { ComptrollerInterface, Action } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { IXVS } from \"../Tokens/XVS/IXVS.sol\";\n\ncontract VenusLens is ExponentialNoError {\n /// @notice Blocks Per Day\n uint public constant BLOCKS_PER_DAY = 192000;\n\n /// @notice Total actions available on VToken\n uint public constant VTOKEN_ACTIONS = 8;\n\n struct VenusMarketState {\n uint224 index;\n uint32 block;\n }\n\n struct VTokenMetadata {\n address vToken;\n uint exchangeRateCurrent;\n uint supplyRatePerBlock;\n uint borrowRatePerBlock;\n uint reserveFactorMantissa;\n uint totalBorrows;\n uint totalReserves;\n uint totalSupply;\n uint totalCash;\n bool isListed;\n uint collateralFactorMantissa;\n address underlyingAssetAddress;\n uint vTokenDecimals;\n uint underlyingDecimals;\n uint venusSupplySpeed;\n uint venusBorrowSpeed;\n uint dailySupplyXvs;\n uint dailyBorrowXvs;\n uint pausedActions;\n uint liquidationThresholdMantissa;\n uint liquidationIncentiveMantissa;\n bool isBorrowAllowed;\n uint96 poolId;\n }\n\n struct VTokenBalances {\n address vToken;\n uint balanceOf;\n uint borrowBalanceCurrent;\n uint balanceOfUnderlying;\n uint tokenBalance;\n uint tokenAllowance;\n }\n\n struct VTokenUnderlyingPrice {\n address vToken;\n uint underlyingPrice;\n }\n\n struct AccountLimits {\n VToken[] markets;\n uint liquidity;\n uint shortfall;\n }\n\n struct XVSBalanceMetadata {\n uint balance;\n uint votes;\n address delegate;\n }\n\n struct XVSBalanceMetadataExt {\n uint balance;\n uint votes;\n address delegate;\n uint allocated;\n }\n\n struct VenusVotes {\n uint blockNumber;\n uint votes;\n }\n\n struct ClaimVenusLocalVariables {\n uint totalRewards;\n uint224 borrowIndex;\n uint32 borrowBlock;\n uint224 supplyIndex;\n uint32 supplyBlock;\n }\n\n /**\n * @dev Struct for Pending Rewards for per market\n */\n struct PendingReward {\n address vTokenAddress;\n uint256 amount;\n }\n\n /**\n * @dev Struct for Reward of a single reward token.\n */\n struct RewardSummary {\n address distributorAddress;\n address rewardTokenAddress;\n uint256 totalRewards;\n PendingReward[] pendingRewards;\n }\n\n /// @notice Holds full market information for a single vToken within a specific pool\n struct MarketData {\n uint96 poolId;\n string poolLabel;\n address vToken;\n bool isListed;\n uint256 collateralFactor;\n bool isVenus;\n uint256 liquidationThreshold;\n uint256 liquidationIncentive;\n bool isBorrowAllowed;\n }\n\n /// @notice Struct representing a pool and its associated markets\n struct PoolWithMarkets {\n uint96 poolId;\n string label;\n bool isActive;\n bool allowCorePoolFallback;\n MarketData[] markets;\n }\n\n /// @notice Struct representing comptroller markets mapping return type\n struct MarketsInfo {\n bool isListed;\n uint collateralFactorMantissa;\n bool isVenus;\n uint liquidationThresholdMantissa;\n uint liquidationIncentiveMantissa;\n uint96 poolId;\n bool isBorrowAllowed;\n }\n\n /// @notice Thrown when a given pool ID does not exist\n error PoolDoesNotExist(uint96 poolId);\n\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\n error InvalidOperationForCorePool();\n\n /**\n * @notice Query the metadata of a vToken by its address\n * @param vToken The address of the vToken to fetch VTokenMetadata\n * @return VTokenMetadata struct with vToken supply and borrow information.\n */\n function vTokenMetadata(VToken vToken) public returns (VTokenMetadata memory) {\n uint exchangeRateCurrent = vToken.exchangeRateCurrent();\n address comptrollerAddress = address(vToken.comptroller());\n ComptrollerInterface comptroller = ComptrollerInterface(comptrollerAddress);\n MarketsInfo memory market;\n (\n market.isListed,\n market.collateralFactorMantissa,\n market.isVenus,\n market.liquidationThresholdMantissa,\n market.liquidationIncentiveMantissa,\n market.poolId,\n market.isBorrowAllowed\n ) = comptroller.markets(address(vToken));\n address underlyingAssetAddress;\n uint underlyingDecimals;\n\n if (compareStrings(vToken.symbol(), \"vBNB\")) {\n underlyingAssetAddress = address(0);\n underlyingDecimals = 18;\n } else {\n VBep20 vBep20 = VBep20(address(vToken));\n underlyingAssetAddress = vBep20.underlying();\n underlyingDecimals = IERC20Metadata(vBep20.underlying()).decimals();\n }\n\n uint venusSupplySpeedPerBlock = comptroller.venusSupplySpeeds(address(vToken));\n uint venusBorrowSpeedPerBlock = comptroller.venusBorrowSpeeds(address(vToken));\n\n uint256 pausedActions;\n\n for (uint8 i; i <= VTOKEN_ACTIONS; ++i) {\n uint256 paused = comptroller.actionPaused(address(vToken), Action(i)) ? 1 : 0;\n pausedActions |= paused << i;\n }\n\n return\n VTokenMetadata({\n vToken: address(vToken),\n exchangeRateCurrent: exchangeRateCurrent,\n supplyRatePerBlock: vToken.supplyRatePerBlock(),\n borrowRatePerBlock: vToken.borrowRatePerBlock(),\n reserveFactorMantissa: vToken.reserveFactorMantissa(),\n totalBorrows: vToken.totalBorrows(),\n totalReserves: vToken.totalReserves(),\n totalSupply: vToken.totalSupply(),\n totalCash: vToken.getCash(),\n isListed: market.isListed,\n collateralFactorMantissa: market.collateralFactorMantissa,\n underlyingAssetAddress: underlyingAssetAddress,\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n venusSupplySpeed: venusSupplySpeedPerBlock,\n venusBorrowSpeed: venusBorrowSpeedPerBlock,\n dailySupplyXvs: venusSupplySpeedPerBlock * BLOCKS_PER_DAY,\n dailyBorrowXvs: venusBorrowSpeedPerBlock * BLOCKS_PER_DAY,\n pausedActions: pausedActions,\n liquidationThresholdMantissa: market.liquidationThresholdMantissa,\n liquidationIncentiveMantissa: market.liquidationIncentiveMantissa,\n isBorrowAllowed: market.isBorrowAllowed,\n poolId: market.poolId\n });\n }\n\n /**\n * @notice Get VTokenMetadata for an array of vToken addresses\n * @param vTokens Array of vToken addresses to fetch VTokenMetadata\n * @return Array of structs with vToken supply and borrow information.\n */\n function vTokenMetadataAll(VToken[] calldata vTokens) external returns (VTokenMetadata[] memory) {\n uint vTokenCount = vTokens.length;\n VTokenMetadata[] memory res = new VTokenMetadata[](vTokenCount);\n for (uint i = 0; i < vTokenCount; i++) {\n res[i] = vTokenMetadata(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Get amount of XVS distributed daily to an account\n * @param account Address of account to fetch the daily XVS distribution\n * @param comptrollerAddress Address of the comptroller proxy\n * @return Amount of XVS distributed daily to an account\n */\n function getDailyXVS(address payable account, address comptrollerAddress) external returns (uint) {\n ComptrollerInterface comptrollerInstance = ComptrollerInterface(comptrollerAddress);\n VToken[] memory vTokens = comptrollerInstance.getAllMarkets();\n uint dailyXvsPerAccount = 0;\n\n for (uint i = 0; i < vTokens.length; i++) {\n VToken vToken = vTokens[i];\n if (!compareStrings(vToken.symbol(), \"vUST\") && !compareStrings(vToken.symbol(), \"vLUNA\")) {\n VTokenMetadata memory metaDataItem = vTokenMetadata(vToken);\n\n //get balanceOfUnderlying and borrowBalanceCurrent from vTokenBalance\n VTokenBalances memory vTokenBalanceInfo = vTokenBalances(vToken, account);\n\n VTokenUnderlyingPrice memory underlyingPriceResponse = vTokenUnderlyingPrice(vToken);\n uint underlyingPrice = underlyingPriceResponse.underlyingPrice;\n Exp memory underlyingPriceMantissa = Exp({ mantissa: underlyingPrice });\n\n //get dailyXvsSupplyMarket\n uint dailyXvsSupplyMarket = 0;\n uint supplyInUsd = mul_ScalarTruncate(underlyingPriceMantissa, vTokenBalanceInfo.balanceOfUnderlying);\n uint marketTotalSupply = (metaDataItem.totalSupply * metaDataItem.exchangeRateCurrent) / 1e18;\n uint marketTotalSupplyInUsd = mul_ScalarTruncate(underlyingPriceMantissa, marketTotalSupply);\n\n if (marketTotalSupplyInUsd > 0) {\n dailyXvsSupplyMarket = (metaDataItem.dailySupplyXvs * supplyInUsd) / marketTotalSupplyInUsd;\n }\n\n //get dailyXvsBorrowMarket\n uint dailyXvsBorrowMarket = 0;\n uint borrowsInUsd = mul_ScalarTruncate(underlyingPriceMantissa, vTokenBalanceInfo.borrowBalanceCurrent);\n uint marketTotalBorrowsInUsd = mul_ScalarTruncate(underlyingPriceMantissa, metaDataItem.totalBorrows);\n\n if (marketTotalBorrowsInUsd > 0) {\n dailyXvsBorrowMarket = (metaDataItem.dailyBorrowXvs * borrowsInUsd) / marketTotalBorrowsInUsd;\n }\n\n dailyXvsPerAccount += dailyXvsSupplyMarket + dailyXvsBorrowMarket;\n }\n }\n\n return dailyXvsPerAccount;\n }\n\n /**\n * @notice Get the current vToken balance (outstanding borrows) for an account\n * @param vToken Address of the token to check the balance of\n * @param account Account address to fetch the balance of\n * @return VTokenBalances with token balance information\n */\n function vTokenBalances(VToken vToken, address payable account) public returns (VTokenBalances memory) {\n uint balanceOf = vToken.balanceOf(account);\n uint borrowBalanceCurrent = vToken.borrowBalanceCurrent(account);\n uint balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n uint tokenBalance;\n uint tokenAllowance;\n\n if (compareStrings(vToken.symbol(), \"vBNB\")) {\n tokenBalance = account.balance;\n tokenAllowance = account.balance;\n } else {\n VBep20 vBep20 = VBep20(address(vToken));\n IERC20Metadata underlying = IERC20Metadata(vBep20.underlying());\n tokenBalance = underlying.balanceOf(account);\n tokenAllowance = underlying.allowance(account, address(vToken));\n }\n\n return\n VTokenBalances({\n vToken: address(vToken),\n balanceOf: balanceOf,\n borrowBalanceCurrent: borrowBalanceCurrent,\n balanceOfUnderlying: balanceOfUnderlying,\n tokenBalance: tokenBalance,\n tokenAllowance: tokenAllowance\n });\n }\n\n /**\n * @notice Get the current vToken balances (outstanding borrows) for all vTokens on an account\n * @param vTokens Addresses of the tokens to check the balance of\n * @param account Account address to fetch the balance of\n * @return VTokenBalances Array with token balance information\n */\n function vTokenBalancesAll(\n VToken[] calldata vTokens,\n address payable account\n ) external returns (VTokenBalances[] memory) {\n uint vTokenCount = vTokens.length;\n VTokenBalances[] memory res = new VTokenBalances[](vTokenCount);\n for (uint i = 0; i < vTokenCount; i++) {\n res[i] = vTokenBalances(vTokens[i], account);\n }\n return res;\n }\n\n /**\n * @notice Get the price for the underlying asset of a vToken\n * @param vToken address of the vToken\n * @return response struct with underlyingPrice info of vToken\n */\n function vTokenUnderlyingPrice(VToken vToken) public view returns (VTokenUnderlyingPrice memory) {\n ComptrollerInterface comptroller = ComptrollerInterface(address(vToken.comptroller()));\n ResilientOracleInterface priceOracle = comptroller.oracle();\n\n return\n VTokenUnderlyingPrice({\n vToken: address(vToken),\n underlyingPrice: priceOracle.getUnderlyingPrice(address(vToken))\n });\n }\n\n /**\n * @notice Query the underlyingPrice of an array of vTokens\n * @param vTokens Array of vToken addresses\n * @return array of response structs with underlying price information of vTokens\n */\n function vTokenUnderlyingPriceAll(\n VToken[] calldata vTokens\n ) external view returns (VTokenUnderlyingPrice[] memory) {\n uint vTokenCount = vTokens.length;\n VTokenUnderlyingPrice[] memory res = new VTokenUnderlyingPrice[](vTokenCount);\n for (uint i = 0; i < vTokenCount; i++) {\n res[i] = vTokenUnderlyingPrice(vTokens[i]);\n }\n return res;\n }\n\n /**\n * @notice Query the account liquidity and shortfall of an account\n * @param comptroller Address of comptroller proxy\n * @param account Address of the account to query\n * @return Struct with markets user has entered, liquidity, and shortfall of the account\n */\n function getAccountLimits(\n ComptrollerInterface comptroller,\n address account\n ) public view returns (AccountLimits memory) {\n (uint errorCode, uint liquidity, uint shortfall) = comptroller.getAccountLiquidity(account);\n require(errorCode == 0, \"account liquidity error\");\n\n return AccountLimits({ markets: comptroller.getAssetsIn(account), liquidity: liquidity, shortfall: shortfall });\n }\n\n /**\n * @notice Query the XVSBalance info of an account\n * @param xvs XVS contract address\n * @param account Account address\n * @return Struct with XVS balance and voter details\n */\n function getXVSBalanceMetadata(IXVS xvs, address account) external view returns (XVSBalanceMetadata memory) {\n return\n XVSBalanceMetadata({\n balance: xvs.balanceOf(account),\n votes: uint256(xvs.getCurrentVotes(account)),\n delegate: xvs.delegates(account)\n });\n }\n\n /**\n * @notice Query the XVSBalance extended info of an account\n * @param xvs XVS contract address\n * @param comptroller Comptroller proxy contract address\n * @param account Account address\n * @return Struct with XVS balance and voter details and XVS allocation\n */\n function getXVSBalanceMetadataExt(\n IXVS xvs,\n ComptrollerInterface comptroller,\n address account\n ) external returns (XVSBalanceMetadataExt memory) {\n uint balance = xvs.balanceOf(account);\n comptroller.claimVenus(account);\n uint newBalance = xvs.balanceOf(account);\n uint accrued = comptroller.venusAccrued(account);\n uint total = add_(accrued, newBalance, \"sum xvs total\");\n uint allocated = sub_(total, balance, \"sub allocated\");\n\n return\n XVSBalanceMetadataExt({\n balance: balance,\n votes: uint256(xvs.getCurrentVotes(account)),\n delegate: xvs.delegates(account),\n allocated: allocated\n });\n }\n\n /**\n * @notice Query the voting power for an account at a specific list of block numbers\n * @param xvs XVS contract address\n * @param account Address of the account\n * @param blockNumbers Array of blocks to query\n * @return Array of VenusVotes structs with block number and vote count\n */\n function getVenusVotes(\n IXVS xvs,\n address account,\n uint32[] calldata blockNumbers\n ) external view returns (VenusVotes[] memory) {\n VenusVotes[] memory res = new VenusVotes[](blockNumbers.length);\n for (uint i = 0; i < blockNumbers.length; i++) {\n res[i] = VenusVotes({\n blockNumber: uint256(blockNumbers[i]),\n votes: uint256(xvs.getPriorVotes(account, blockNumbers[i]))\n });\n }\n return res;\n }\n\n /**\n * @dev Queries the current supply to calculate rewards for an account\n * @param supplyState VenusMarketState struct\n * @param vToken Address of a vToken\n * @param comptroller Address of the comptroller proxy\n */\n function updateVenusSupplyIndex(\n VenusMarketState memory supplyState,\n address vToken,\n ComptrollerInterface comptroller\n ) internal view {\n uint supplySpeed = comptroller.venusSupplySpeeds(vToken);\n uint blockNumber = block.number;\n uint deltaBlocks = sub_(blockNumber, uint(supplyState.block));\n if (deltaBlocks > 0 && supplySpeed > 0) {\n uint supplyTokens = VToken(vToken).totalSupply();\n uint venusAccrued = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens > 0 ? fraction(venusAccrued, supplyTokens) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: supplyState.index }), ratio);\n supplyState.index = safe224(index.mantissa, \"new index overflows\");\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n supplyState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n /**\n * @dev Queries the current borrow to calculate rewards for an account\n * @param borrowState VenusMarketState struct\n * @param vToken Address of a vToken\n * @param comptroller Address of the comptroller proxy\n */\n function updateVenusBorrowIndex(\n VenusMarketState memory borrowState,\n address vToken,\n Exp memory marketBorrowIndex,\n ComptrollerInterface comptroller\n ) internal view {\n uint borrowSpeed = comptroller.venusBorrowSpeeds(vToken);\n uint blockNumber = block.number;\n uint deltaBlocks = sub_(blockNumber, uint(borrowState.block));\n if (deltaBlocks > 0 && borrowSpeed > 0) {\n uint borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint venusAccrued = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount > 0 ? fraction(venusAccrued, borrowAmount) : Double({ mantissa: 0 });\n Double memory index = add_(Double({ mantissa: borrowState.index }), ratio);\n borrowState.index = safe224(index.mantissa, \"new index overflows\");\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n } else if (deltaBlocks > 0) {\n borrowState.block = safe32(blockNumber, \"block number overflows\");\n }\n }\n\n /**\n * @dev Calculate available rewards for an account's supply\n * @param supplyState VenusMarketState struct\n * @param vToken Address of a vToken\n * @param supplier Address of the account supplying\n * @param comptroller Address of the comptroller proxy\n * @return Undistributed earned XVS from supplies\n */\n function distributeSupplierVenus(\n VenusMarketState memory supplyState,\n address vToken,\n address supplier,\n ComptrollerInterface comptroller\n ) internal view returns (uint) {\n Double memory supplyIndex = Double({ mantissa: supplyState.index });\n Double memory supplierIndex = Double({ mantissa: comptroller.venusSupplierIndex(vToken, supplier) });\n if (supplierIndex.mantissa == 0 && supplyIndex.mantissa > 0) {\n supplierIndex.mantissa = comptroller.venusInitialIndex();\n }\n\n Double memory deltaIndex = sub_(supplyIndex, supplierIndex);\n uint supplierTokens = VToken(vToken).balanceOf(supplier);\n uint supplierDelta = mul_(supplierTokens, deltaIndex);\n return supplierDelta;\n }\n\n /**\n * @dev Calculate available rewards for an account's borrows\n * @param borrowState VenusMarketState struct\n * @param vToken Address of a vToken\n * @param borrower Address of the account borrowing\n * @param marketBorrowIndex vToken Borrow index\n * @param comptroller Address of the comptroller proxy\n * @return Undistributed earned XVS from borrows\n */\n function distributeBorrowerVenus(\n VenusMarketState memory borrowState,\n address vToken,\n address borrower,\n Exp memory marketBorrowIndex,\n ComptrollerInterface comptroller\n ) internal view returns (uint) {\n Double memory borrowIndex = Double({ mantissa: borrowState.index });\n Double memory borrowerIndex = Double({ mantissa: comptroller.venusBorrowerIndex(vToken, borrower) });\n if (borrowerIndex.mantissa > 0) {\n Double memory deltaIndex = sub_(borrowIndex, borrowerIndex);\n uint borrowerAmount = div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex);\n uint borrowerDelta = mul_(borrowerAmount, deltaIndex);\n return borrowerDelta;\n }\n return 0;\n }\n\n /**\n * @notice Calculate the total XVS tokens pending and accrued by a user account\n * @param holder Account to query pending XVS\n * @param comptroller Address of the comptroller\n * @return Reward object contraining the totalRewards and pending rewards for each market\n */\n function pendingRewards(\n address holder,\n ComptrollerInterface comptroller\n ) external view returns (RewardSummary memory) {\n VToken[] memory vTokens = comptroller.getAllMarkets();\n ClaimVenusLocalVariables memory vars;\n RewardSummary memory rewardSummary;\n rewardSummary.distributorAddress = address(comptroller);\n rewardSummary.rewardTokenAddress = comptroller.getXVSAddress();\n rewardSummary.totalRewards = comptroller.venusAccrued(holder);\n rewardSummary.pendingRewards = new PendingReward[](vTokens.length);\n for (uint i; i < vTokens.length; ++i) {\n (vars.borrowIndex, vars.borrowBlock) = comptroller.venusBorrowState(address(vTokens[i]));\n VenusMarketState memory borrowState = VenusMarketState({\n index: vars.borrowIndex,\n block: vars.borrowBlock\n });\n\n (vars.supplyIndex, vars.supplyBlock) = comptroller.venusSupplyState(address(vTokens[i]));\n VenusMarketState memory supplyState = VenusMarketState({\n index: vars.supplyIndex,\n block: vars.supplyBlock\n });\n\n Exp memory borrowIndex = Exp({ mantissa: vTokens[i].borrowIndex() });\n\n PendingReward memory marketReward;\n marketReward.vTokenAddress = address(vTokens[i]);\n\n updateVenusBorrowIndex(borrowState, address(vTokens[i]), borrowIndex, comptroller);\n uint256 borrowReward = distributeBorrowerVenus(\n borrowState,\n address(vTokens[i]),\n holder,\n borrowIndex,\n comptroller\n );\n\n updateVenusSupplyIndex(supplyState, address(vTokens[i]), comptroller);\n uint256 supplyReward = distributeSupplierVenus(supplyState, address(vTokens[i]), holder, comptroller);\n\n marketReward.amount = add_(borrowReward, supplyReward);\n rewardSummary.pendingRewards[i] = marketReward;\n }\n return rewardSummary;\n }\n\n /**\n * @notice Returns all pools (including the Core Pool) along with their associated market data\n * @param comptroller The Comptroller contract to query\n * @return poolsData An array of PoolWithMarkets structs, each containing pool info and its markets\n */\n function getAllPoolsData(\n ComptrollerInterface comptroller\n ) external view returns (PoolWithMarkets[] memory poolsData) {\n uint96 lastPoolId = comptroller.lastPoolId();\n poolsData = new PoolWithMarkets[](lastPoolId + 1);\n\n poolsData[0] = PoolWithMarkets({\n poolId: 0,\n label: \"Core Pool\",\n isActive: true, // dummy value — not applicable to core pool\n allowCorePoolFallback: true, // dummy value — not applicable to core pool\n markets: getCorePoolMarketsData(comptroller)\n });\n\n for (uint96 i = 1; i <= lastPoolId; ++i) {\n (string memory label, bool isActive, bool allowCorePoolFallback) = comptroller.pools(i);\n\n poolsData[i] = PoolWithMarkets({\n poolId: i,\n label: label,\n isActive: isActive,\n allowCorePoolFallback: allowCorePoolFallback,\n markets: getMarketsDataByPool(i, comptroller)\n });\n }\n }\n\n /**\n * @notice Retrieves full market data for all vTokens in a specific pool (excluding the Core Pool)\n * @param poolId The pool ID to fetch data for\n * @param comptroller The address of the Comptroller contract\n * @return result An array of MarketData structs containing detailed market info for the given pool\n * @custom:error PoolDoesNotExist Reverts if the given pool ID does not exist\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool (`poolId = 0`)\n */\n function getMarketsDataByPool(\n uint96 poolId,\n ComptrollerInterface comptroller\n ) public view returns (MarketData[] memory result) {\n if (poolId > comptroller.lastPoolId()) revert PoolDoesNotExist(poolId);\n if (poolId == comptroller.corePoolId()) revert InvalidOperationForCorePool();\n\n address[] memory vTokens = comptroller.getPoolVTokens(poolId);\n uint256 length = vTokens.length;\n result = new MarketData[](length);\n\n (string memory label, , ) = comptroller.pools(poolId);\n\n for (uint256 i; i < length; ++i) {\n (\n bool isListed,\n uint256 collateralFactor,\n bool isVenus,\n uint256 liquidationThreshold,\n uint256 liquidationIncentive,\n uint96 marketPoolId,\n bool isBorrowAllowed\n ) = comptroller.poolMarkets(poolId, vTokens[i]);\n\n result[i] = MarketData({\n poolId: marketPoolId,\n poolLabel: label,\n vToken: vTokens[i],\n isListed: isListed,\n collateralFactor: collateralFactor,\n isVenus: isVenus,\n liquidationThreshold: liquidationThreshold,\n liquidationIncentive: liquidationIncentive,\n isBorrowAllowed: isBorrowAllowed\n });\n }\n }\n\n /**\n * @notice Retrieves full market data for all vTokens in the Core Pool (poolId 0)\n * @param comptroller The address of the Comptroller contract\n * @return result An array of MarketData structs containing detailed market info for the core pool\n */\n function getCorePoolMarketsData(ComptrollerInterface comptroller) public view returns (MarketData[] memory result) {\n VToken[] memory vTokens = comptroller.getAllMarkets();\n uint256 length = vTokens.length;\n result = new MarketData[](length);\n\n string memory label = \"Core\";\n\n for (uint256 i; i < length; ++i) {\n (\n bool isListed,\n uint256 collateralFactor,\n bool isVenus,\n uint256 liquidationThreshold,\n uint256 liquidationIncentive,\n uint96 marketPoolId,\n bool isBorrowAllowed\n ) = comptroller.markets(address(vTokens[i]));\n\n result[i] = MarketData({\n poolId: marketPoolId,\n poolLabel: label,\n vToken: address(vTokens[i]),\n isListed: isListed,\n collateralFactor: collateralFactor,\n isVenus: isVenus,\n liquidationThreshold: liquidationThreshold,\n liquidationIncentive: liquidationIncentive,\n isBorrowAllowed: isBorrowAllowed\n });\n }\n }\n\n // utilities\n /**\n * @notice Compares if two strings are equal\n * @param a First string to compare\n * @param b Second string to compare\n * @return Boolean depending on if the strings are equal\n */\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}" + }, + "contracts/Liquidator/Liquidator.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"../external/IProtocolShareReserve.sol\";\nimport { IWBNB } from \"../external/IWBNB.sol\";\nimport { LiquidatorStorage } from \"./LiquidatorStorage.sol\";\nimport { IComptroller, IVToken, IVBep20, IVBNB, IVAIController } from \"../InterfacesV8.sol\";\n\ncontract Liquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable, LiquidatorStorage, AccessControlledV8 {\n /// @notice Address of vBNB contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IVBNB public immutable vBnb;\n\n /// @notice Address of Venus Unitroller contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IComptroller public immutable comptroller;\n\n /// @notice Address of VAIUnitroller contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IVAIController public immutable vaiController;\n\n /// @notice Address of wBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable wBNB;\n\n /// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\n uint256 internal constant MANTISSA_ONE = 1e18;\n\n /* Events */\n\n /// @notice Emitted when the percent of the seized amount that goes to treasury changes.\n event NewLiquidationTreasuryPercent(uint256 oldPercent, uint256 newPercent);\n\n /// @notice Emitted when a borrow is liquidated\n event LiquidateBorrowedTokens(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address vTokenBorrowed,\n address indexed vTokenCollateral,\n uint256 seizeTokensForTreasury,\n uint256 seizeTokensForLiquidator\n );\n\n /// @notice Emitted when the liquidation is restricted for a borrower\n event LiquidationRestricted(address indexed borrower);\n\n /// @notice Emitted when the liquidation restrictions are removed for a borrower\n event LiquidationRestrictionsDisabled(address indexed borrower);\n\n /// @notice Emitted when a liquidator is added to the allowedLiquidatorsByAccount mapping\n event AllowlistEntryAdded(address indexed borrower, address indexed liquidator);\n\n /// @notice Emitted when a liquidator is removed from the allowedLiquidatorsByAccount mapping\n event AllowlistEntryRemoved(address indexed borrower, address indexed liquidator);\n\n /// @notice Emitted when the amount of minLiquidatableVAI is updated\n event NewMinLiquidatableVAI(uint256 oldMinLiquidatableVAI, uint256 newMinLiquidatableVAI);\n\n /// @notice Emitted when the length of chunk gets updated\n event NewPendingRedeemChunkLength(uint256 oldPendingRedeemChunkLength, uint256 newPendingRedeemChunkLength);\n\n /// @notice Emitted when force liquidation is paused\n event ForceVAILiquidationPaused(address indexed sender);\n\n /// @notice Emitted when force liquidation is resumed\n event ForceVAILiquidationResumed(address indexed sender);\n\n /// @notice Emitted when new address of protocol share reserve is set\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserves);\n\n /// @notice Emitted when reserves are reduced from liquidator contract to protocol share reserves\n event ProtocolLiquidationIncentiveTransferred(address indexed sender, address indexed token, uint256 reducedAmount);\n\n /* Errors */\n\n /// @notice Thrown if the liquidation is restricted and the liquidator is not in the allowedLiquidatorsByAccount mapping\n error LiquidationNotAllowed(address borrower, address liquidator);\n\n /// @notice Thrown if VToken transfer fails after the liquidation\n error VTokenTransferFailed(address from, address to, uint256 amount);\n\n /// @notice Thrown if the liquidation is not successful (the error code is from TokenErrorReporter)\n error LiquidationFailed(uint256 errorCode);\n\n /// @notice Thrown if trying to restrict liquidations for an already restricted borrower\n error AlreadyRestricted(address borrower);\n\n /// @notice Thrown if trying to unrestrict liquidations for a borrower that is not restricted\n error NoRestrictionsExist(address borrower);\n\n /// @notice Thrown if the liquidator is already in the allowedLiquidatorsByAccount mapping\n error AlreadyAllowed(address borrower, address liquidator);\n\n /// @notice Thrown if trying to remove a liquidator that is not in the allowedLiquidatorsByAccount mapping\n error AllowlistEntryNotFound(address borrower, address liquidator);\n\n /// @notice Thrown if BNB amount sent with the transaction doesn't correspond to the\n /// intended BNB repayment\n error WrongTransactionAmount(uint256 expected, uint256 actual);\n\n /// @notice Thrown if trying to set treasury percent larger than the liquidation profit\n error TreasuryPercentTooHigh(uint256 maxTreasuryPercentMantissa, uint256 treasuryPercentMantissa_);\n\n /// @notice Thrown if trying to liquidate any token when VAI debt is too high\n error VAIDebtTooHigh(uint256 vaiDebt, uint256 minLiquidatableVAI);\n\n /// @notice Thrown when vToken is not listed\n error MarketNotListed(address vToken);\n\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @param comptroller_ The address of the Comptroller contract\n /// @param vBnb_ The address of the VBNB\n /// @param wBNB_ The address of wBNB\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address comptroller_, address payable vBnb_, address wBNB_) {\n ensureNonzeroAddress(vBnb_);\n ensureNonzeroAddress(comptroller_);\n ensureNonzeroAddress(wBNB_);\n vBnb = IVBNB(vBnb_);\n wBNB = wBNB_;\n comptroller = IComptroller(comptroller_);\n vaiController = IVAIController(IComptroller(comptroller_).vaiController());\n _disableInitializers();\n }\n\n receive() external payable {}\n\n /// @notice Initializer for the implementation contract.\n /// @param treasuryPercentMantissa_ Treasury share, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)\n /// @param accessControlManager_ address of access control manager\n /// @param protocolShareReserve_ The address of the protocol share reserve contract\n function initialize(\n uint256 treasuryPercentMantissa_,\n address accessControlManager_,\n address protocolShareReserve_\n ) external virtual reinitializer(2) {\n __Liquidator_init(treasuryPercentMantissa_, accessControlManager_, protocolShareReserve_);\n }\n\n /// @dev Liquidator initializer for derived contracts.\n /// @param treasuryPercentMantissa_ Treasury share, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)\n /// @param accessControlManager_ address of access control manager\n /// @param protocolShareReserve_ The address of the protocol share reserve contract\n function __Liquidator_init(\n uint256 treasuryPercentMantissa_,\n address accessControlManager_,\n address protocolShareReserve_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __ReentrancyGuard_init();\n __Liquidator_init_unchained(treasuryPercentMantissa_, protocolShareReserve_);\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /// @dev Liquidator initializer for derived contracts that doesn't call parent initializers.\n /// @param treasuryPercentMantissa_ Treasury share, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)\n /// @param protocolShareReserve_ The address of the protocol share reserve contract\n function __Liquidator_init_unchained(\n uint256 treasuryPercentMantissa_,\n address protocolShareReserve_\n ) internal onlyInitializing {\n validateTreasuryPercentMantissa(treasuryPercentMantissa_);\n treasuryPercentMantissa = treasuryPercentMantissa_;\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /// @notice An admin function to restrict liquidations to allowed addresses only.\n /// @dev Use {addTo,removeFrom}AllowList to configure the allowed addresses.\n /// @param borrower The address of the borrower\n function restrictLiquidation(address borrower) external {\n _checkAccessAllowed(\"restrictLiquidation(address)\");\n if (liquidationRestricted[borrower]) {\n revert AlreadyRestricted(borrower);\n }\n liquidationRestricted[borrower] = true;\n emit LiquidationRestricted(borrower);\n }\n\n /// @notice An admin function to remove restrictions for liquidations.\n /// @dev Does not impact the allowedLiquidatorsByAccount mapping for the borrower, just turns off the check.\n /// @param borrower The address of the borrower\n function unrestrictLiquidation(address borrower) external {\n _checkAccessAllowed(\"unrestrictLiquidation(address)\");\n if (!liquidationRestricted[borrower]) {\n revert NoRestrictionsExist(borrower);\n }\n liquidationRestricted[borrower] = false;\n emit LiquidationRestrictionsDisabled(borrower);\n }\n\n /// @notice An admin function to add the liquidator to the allowedLiquidatorsByAccount mapping for a certain\n /// borrower. If the liquidations are restricted, only liquidators from the\n /// allowedLiquidatorsByAccount mapping can participate in liquidating the positions of this borrower.\n /// @param borrower The address of the borrower\n /// @param borrower The address of the liquidator\n function addToAllowlist(address borrower, address liquidator) external {\n _checkAccessAllowed(\"addToAllowlist(address,address)\");\n if (allowedLiquidatorsByAccount[borrower][liquidator]) {\n revert AlreadyAllowed(borrower, liquidator);\n }\n allowedLiquidatorsByAccount[borrower][liquidator] = true;\n emit AllowlistEntryAdded(borrower, liquidator);\n }\n\n /// @notice An admin function to remove the liquidator from the allowedLiquidatorsByAccount mapping of a certain\n /// borrower. If the liquidations are restricted, this liquidator will not be\n /// able to liquidate the positions of this borrower.\n /// @param borrower The address of the borrower\n /// @param borrower The address of the liquidator\n function removeFromAllowlist(address borrower, address liquidator) external {\n _checkAccessAllowed(\"removeFromAllowlist(address,address)\");\n if (!allowedLiquidatorsByAccount[borrower][liquidator]) {\n revert AllowlistEntryNotFound(borrower, liquidator);\n }\n allowedLiquidatorsByAccount[borrower][liquidator] = false;\n emit AllowlistEntryRemoved(borrower, liquidator);\n }\n\n /// @notice Liquidates a borrow and splits the seized amount between protocol share reserve and\n /// liquidator. The liquidators should use this interface instead of calling\n /// vToken.liquidateBorrow(...) directly.\n /// @notice Checks force VAI liquidation first; vToken should be address of vaiController if vaiDebt is greater than threshold\n /// @notice For BNB borrows msg.value should be equal to repayAmount; otherwise msg.value\n /// should be zero.\n /// @param vToken Borrowed vToken\n /// @param borrower The address of the borrower\n /// @param repayAmount The amount to repay on behalf of the borrower\n /// @param vTokenCollateral The collateral to seize\n function liquidateBorrow(\n address vToken,\n address borrower,\n uint256 repayAmount,\n IVToken vTokenCollateral\n ) external payable nonReentrant {\n ensureNonzeroAddress(borrower);\n checkRestrictions(borrower, msg.sender);\n (bool isListed, , ) = IComptroller(comptroller).markets(address(vTokenCollateral));\n if (!isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n _checkForceVAILiquidate(vToken, borrower);\n uint256 ourBalanceBefore = vTokenCollateral.balanceOf(address(this));\n if (vToken == address(vBnb)) {\n if (repayAmount != msg.value) {\n revert WrongTransactionAmount(repayAmount, msg.value);\n }\n vBnb.liquidateBorrow{ value: msg.value }(borrower, vTokenCollateral);\n } else {\n if (msg.value != 0) {\n revert WrongTransactionAmount(0, msg.value);\n }\n if (vToken == address(vaiController)) {\n _liquidateVAI(borrower, repayAmount, vTokenCollateral);\n } else {\n _liquidateBep20(IVBep20(vToken), borrower, repayAmount, vTokenCollateral);\n }\n }\n uint256 ourBalanceAfter = vTokenCollateral.balanceOf(address(this));\n uint256 seizedAmount = ourBalanceAfter - ourBalanceBefore;\n (uint256 ours, uint256 theirs) = _distributeLiquidationIncentive(borrower, vTokenCollateral, seizedAmount);\n _reduceReservesInternal();\n emit LiquidateBorrowedTokens(\n msg.sender,\n borrower,\n repayAmount,\n vToken,\n address(vTokenCollateral),\n ours,\n theirs\n );\n }\n\n /// @notice Sets the new percent of the seized amount that goes to treasury. Should\n /// be less than or equal to comptroller.liquidationIncentiveMantissa().sub(1e18).\n /// @param newTreasuryPercentMantissa New treasury percent (scaled by 10^18).\n function setTreasuryPercent(uint256 newTreasuryPercentMantissa) external {\n _checkAccessAllowed(\"setTreasuryPercent(uint256)\");\n validateTreasuryPercentMantissa(newTreasuryPercentMantissa);\n emit NewLiquidationTreasuryPercent(treasuryPercentMantissa, newTreasuryPercentMantissa);\n treasuryPercentMantissa = newTreasuryPercentMantissa;\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Reduce the reserves of the pending accumulated reserves\n */\n function reduceReserves() external nonReentrant {\n _reduceReservesInternal();\n }\n\n function _reduceReservesInternal() internal {\n uint256 _pendingRedeemLength = pendingRedeem.length;\n uint256 range = _pendingRedeemLength >= pendingRedeemChunkLength\n ? pendingRedeemChunkLength\n : _pendingRedeemLength;\n for (uint256 index = range; index > 0; ) {\n address vToken = pendingRedeem[index - 1];\n uint256 vTokenBalance_ = IVToken(vToken).balanceOf(address(this));\n if (_redeemUnderlying(vToken, vTokenBalance_)) {\n if (vToken == address(vBnb)) {\n _reduceBnbReserves();\n } else {\n _reduceVTokenReserves(vToken);\n }\n pendingRedeem[index - 1] = pendingRedeem[pendingRedeem.length - 1];\n pendingRedeem.pop();\n }\n unchecked {\n index--;\n }\n }\n }\n\n /// @dev Transfers BEP20 tokens to self, then approves vToken to take these tokens.\n function _liquidateBep20(IVBep20 vToken, address borrower, uint256 repayAmount, IVToken vTokenCollateral) internal {\n (bool isListed, , ) = IComptroller(comptroller).markets(address(vToken));\n if (!isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n IERC20Upgradeable borrowedToken = IERC20Upgradeable(vToken.underlying());\n uint256 actualRepayAmount = _transferBep20(borrowedToken, msg.sender, address(this), repayAmount);\n borrowedToken.safeApprove(address(vToken), 0);\n borrowedToken.safeApprove(address(vToken), actualRepayAmount);\n requireNoError(vToken.liquidateBorrow(borrower, actualRepayAmount, vTokenCollateral));\n }\n\n /// @dev Transfers BEP20 tokens to self, then approves VAI to take these tokens.\n function _liquidateVAI(address borrower, uint256 repayAmount, IVToken vTokenCollateral) internal {\n IERC20Upgradeable vai = IERC20Upgradeable(vaiController.getVAIAddress());\n vai.safeTransferFrom(msg.sender, address(this), repayAmount);\n vai.safeApprove(address(vaiController), 0);\n vai.safeApprove(address(vaiController), repayAmount);\n\n (uint256 err, ) = vaiController.liquidateVAI(borrower, repayAmount, vTokenCollateral);\n requireNoError(err);\n }\n\n /// @dev Distribute seized collateral between liquidator and protocol share reserve\n function _distributeLiquidationIncentive(\n address borrower,\n IVToken vTokenCollateral,\n uint256 seizedAmount\n ) internal returns (uint256 ours, uint256 theirs) {\n (ours, theirs) = _splitLiquidationIncentive(borrower, address(vTokenCollateral), seizedAmount);\n if (!vTokenCollateral.transfer(msg.sender, theirs)) {\n revert VTokenTransferFailed(address(this), msg.sender, theirs);\n }\n\n if (ours > 0 && !_redeemUnderlying(address(vTokenCollateral), ours)) {\n // Check if asset is already present in pendingRedeem array\n uint256 index;\n for (index; index < pendingRedeem.length; ) {\n if (pendingRedeem[index] == address(vTokenCollateral)) {\n break;\n }\n unchecked {\n index++;\n }\n }\n if (index == pendingRedeem.length) {\n pendingRedeem.push(address(vTokenCollateral));\n }\n } else {\n if (address(vTokenCollateral) == address(vBnb)) {\n _reduceBnbReserves();\n } else {\n _reduceVTokenReserves(address(vTokenCollateral));\n }\n }\n }\n\n /// @dev Wraps BNB to wBNB and sends to protocol share reserve\n function _reduceBnbReserves() private {\n uint256 bnbBalance = address(this).balance;\n IWBNB(wBNB).deposit{ value: bnbBalance }();\n IERC20Upgradeable(wBNB).safeTransfer(protocolShareReserve, bnbBalance);\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n wBNB,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n emit ProtocolLiquidationIncentiveTransferred(msg.sender, wBNB, bnbBalance);\n }\n\n /// @dev Redeem seized collateral to underlying assets\n function _redeemUnderlying(address vToken, uint256 amount) private returns (bool) {\n try IVToken(address(vToken)).redeem(amount) returns (uint256 response) {\n if (response == 0) {\n return true;\n } else {\n return false;\n }\n } catch {\n return false;\n }\n }\n\n /// @dev Transfers seized collateral other than BNB to protocol share reserve\n function _reduceVTokenReserves(address vToken) private {\n address underlying = IVBep20(vToken).underlying();\n uint256 underlyingBalance = IERC20Upgradeable(underlying).balanceOf(address(this));\n IERC20Upgradeable(underlying).safeTransfer(protocolShareReserve, underlyingBalance);\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n emit ProtocolLiquidationIncentiveTransferred(msg.sender, underlying, underlyingBalance);\n }\n\n /// @dev Transfers tokens and returns the actual transfer amount\n function _transferBep20(\n IERC20Upgradeable token,\n address from,\n address to,\n uint256 amount\n ) internal returns (uint256) {\n uint256 prevBalance = token.balanceOf(to);\n token.safeTransferFrom(from, to, amount);\n return token.balanceOf(to) - prevBalance;\n }\n\n /// @dev Computes the amounts that would go to treasury and to the liquidator.\n function _splitLiquidationIncentive(\n address borrower,\n address vTokenCollateral,\n uint256 seizedAmount\n ) internal view returns (uint256 ours, uint256 theirs) {\n uint256 totalIncentive = comptroller.getEffectiveLiquidationIncentive(borrower, vTokenCollateral);\n uint256 bonusMantissa = totalIncentive - MANTISSA_ONE;\n\n // Our share is % of bonus portion only\n uint256 bonusAmount = (seizedAmount * bonusMantissa) / totalIncentive;\n ours = (bonusAmount * treasuryPercentMantissa) / MANTISSA_ONE;\n\n theirs = seizedAmount - ours;\n }\n\n function requireNoError(uint256 errCode) internal pure {\n if (errCode == uint256(0)) {\n return;\n }\n\n revert LiquidationFailed(errCode);\n }\n\n function checkRestrictions(address borrower, address liquidator) internal view {\n if (liquidationRestricted[borrower] && !allowedLiquidatorsByAccount[borrower][liquidator]) {\n revert LiquidationNotAllowed(borrower, liquidator);\n }\n }\n\n function validateTreasuryPercentMantissa(uint256 treasuryPercentMantissa_) internal view {\n if (treasuryPercentMantissa_ > MANTISSA_ONE) {\n revert TreasuryPercentTooHigh(MANTISSA_ONE, treasuryPercentMantissa_);\n }\n }\n\n /// @dev Checks liquidation action in comptroller and vaiDebt with minLiquidatableVAI threshold\n function _checkForceVAILiquidate(address vToken_, address borrower_) private view {\n uint256 _vaiDebt = vaiController.getVAIRepayAmount(borrower_);\n bool _isVAILiquidationPaused = comptroller.actionPaused(address(vaiController), IComptroller.Action.LIQUIDATE);\n bool _isForcedLiquidationEnabled = comptroller.isForcedLiquidationEnabled(vToken_);\n if (\n _isForcedLiquidationEnabled ||\n _isVAILiquidationPaused ||\n !forceVAILiquidate ||\n _vaiDebt < minLiquidatableVAI ||\n vToken_ == address(vaiController)\n ) return;\n revert VAIDebtTooHigh(_vaiDebt, minLiquidatableVAI);\n }\n\n function _setProtocolShareReserve(address protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n emit NewProtocolShareReserve(protocolShareReserve, protocolShareReserve_);\n protocolShareReserve = protocolShareReserve_;\n }\n\n /**\n * @notice Sets the threshold for minimum amount of vaiLiquidate\n * @param minLiquidatableVAI_ New address for the access control\n */\n function setMinLiquidatableVAI(uint256 minLiquidatableVAI_) external {\n _checkAccessAllowed(\"setMinLiquidatableVAI(uint256)\");\n emit NewMinLiquidatableVAI(minLiquidatableVAI, minLiquidatableVAI_);\n minLiquidatableVAI = minLiquidatableVAI_;\n }\n\n /**\n * @notice Length of the pendingRedeem array to be consider while redeeming in Liquidation transaction\n * @param newLength_ Length of the chunk\n */\n function setPendingRedeemChunkLength(uint256 newLength_) external {\n _checkAccessAllowed(\"setPendingRedeemChunkLength(uint256)\");\n require(newLength_ > 0, \"Invalid chunk size\");\n emit NewPendingRedeemChunkLength(pendingRedeemChunkLength, newLength_);\n pendingRedeemChunkLength = newLength_;\n }\n\n /**\n * @notice Pause Force Liquidation of VAI\n */\n function pauseForceVAILiquidate() external {\n _checkAccessAllowed(\"pauseForceVAILiquidate()\");\n require(forceVAILiquidate, \"Force Liquidation of VAI is already Paused\");\n forceVAILiquidate = false;\n emit ForceVAILiquidationPaused(msg.sender);\n }\n\n /**\n * @notice Resume Force Liquidation of VAI\n */\n function resumeForceVAILiquidate() external {\n _checkAccessAllowed(\"resumeForceVAILiquidate()\");\n require(!forceVAILiquidate, \"Force Liquidation of VAI is already resumed\");\n forceVAILiquidate = true;\n emit ForceVAILiquidationResumed(msg.sender);\n }\n\n function renounceOwnership() public override {}\n}\n" + }, + "contracts/Liquidator/LiquidatorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ncontract LiquidatorStorage {\n /* State */\n\n /// @notice Percent of seized amount that goes to treasury.\n uint256 public treasuryPercentMantissa;\n\n /// @notice Mapping of addresses allowed to liquidate an account if liquidationRestricted[borrower] == true\n mapping(address => mapping(address => bool)) public allowedLiquidatorsByAccount;\n\n /// @notice Whether the liquidations are restricted to enabled allowedLiquidatorsByAccount addresses only\n mapping(address => bool) public liquidationRestricted;\n\n /// @notice minimum amount of VAI liquidation threshold\n uint256 public minLiquidatableVAI;\n\n /// @notice check for liquidation of VAI\n bool public forceVAILiquidate;\n\n /// @notice assests whose redeem is pending to reduce reserves\n address[] public pendingRedeem;\n\n /// @notice protocol share reserve contract address\n address public protocolShareReserve;\n\n /// @dev Size of chunk to consider when redeeming underlying at the time of liquidation\n uint256 internal pendingRedeemChunkLength;\n\n /// @notice gap to prevent collision in inheritance\n uint256[49] private __gap;\n}\n" + }, + "contracts/PegStability/IVAI.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IVAI {\n function balanceOf(address usr) external returns (uint256);\n\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n\n function mint(address usr, uint wad) external;\n\n function burn(address usr, uint wad) external;\n}\n" + }, + "contracts/PegStability/PegStability.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IVAI } from \"./IVAI.sol\";\n\n/**\n * @title Peg Stability Contract.\n * @notice Contract for swapping stable token for VAI token and vice versa to maintain the peg stability between them.\n * @author Venus Protocol\n */\ncontract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n // Helper enum for calculation of the fee.\n enum FeeDirection {\n IN,\n OUT\n }\n\n /// @notice The divisor used to convert fees to basis points.\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\n\n /// @notice The mantissa value representing 1 (used for calculations).\n uint256 public constant MANTISSA_ONE = 1e18;\n\n /// @notice The value representing one dollar in the stable token.\n /// @dev Our oracle is returning amount depending on the number of decimals of the stable token. (36 - asset_decimals) E.g. 8 decimal asset = 1e28.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable ONE_DOLLAR;\n\n /// @notice VAI token contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IVAI public immutable VAI;\n\n /// @notice The address of the stable token contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable STABLE_TOKEN_ADDRESS;\n\n /// @notice The address of ResilientOracle contract wrapped in its interface.\n ResilientOracleInterface public oracle;\n\n /// @notice The address of the Venus Treasury contract.\n address public venusTreasury;\n\n /// @notice The incoming stableCoin fee. (Fee for swapStableForVAI).\n uint256 public feeIn;\n\n /// @notice The outgoing stableCoin fee. (Fee for swapVAIForStable).\n uint256 public feeOut;\n\n /// @notice The maximum amount of VAI that can be minted through this contract.\n uint256 public vaiMintCap;\n\n /// @notice The total amount of VAI minted through this contract.\n uint256 public vaiMinted;\n\n /// @notice A flag indicating whether the contract is currently paused or not.\n bool public isPaused;\n\n /// @notice Event emitted when contract is paused.\n event PSMPaused(address indexed admin);\n\n /// @notice Event emitted when the contract is resumed after pause.\n event PSMResumed(address indexed admin);\n\n /// @notice Event emitted when feeIn state var is modified.\n event FeeInChanged(uint256 oldFeeIn, uint256 newFeeIn);\n\n /// @notice Event emitted when feeOut state var is modified.\n event FeeOutChanged(uint256 oldFeeOut, uint256 newFeeOut);\n\n /// @notice Event emitted when vaiMintCap state var is modified.\n event VAIMintCapChanged(uint256 oldCap, uint256 newCap);\n\n /// @notice Event emitted when venusTreasury state var is modified.\n event VenusTreasuryChanged(address indexed oldTreasury, address indexed newTreasury);\n\n /// @notice Event emitted when oracle state var is modified.\n event OracleChanged(address indexed oldOracle, address indexed newOracle);\n\n /// @notice Event emitted when stable token is swapped for VAI.\n event StableForVAISwapped(uint256 stableIn, uint256 vaiOut, uint256 fee);\n\n /// @notice Event emitted when stable token is swapped for VAI.\n event VAIForStableSwapped(uint256 vaiBurnt, uint256 stableOut, uint256 vaiFee);\n\n /// @notice thrown when contract is in paused state\n error Paused();\n\n /// @notice thrown when attempted to pause an already paused contract\n error AlreadyPaused();\n\n /// @notice thrown when attempted to resume the contract if it is already resumed\n error NotPaused();\n\n /// @notice thrown when stable token has more than 18 decimals\n error TooManyDecimals();\n\n /// @notice thrown when fee is >= 100%\n error InvalidFee();\n\n /// @notice thrown when a zero address is passed as a function parameter\n error ZeroAddress();\n\n /// @notice thrown when a zero amount is passed as stable token amount parameter\n error ZeroAmount();\n\n /// @notice thrown when the user doesn't have enough VAI balance to provide for the amount of stable tokens he wishes to get\n error NotEnoughVAI();\n\n /// @notice thrown when the amount of VAI to be burnt exceeds the vaiMinted amount\n error VAIMintedUnderflow();\n\n /// @notice thrown when the VAI transfer to treasury fails\n error VAITransferFail();\n\n /// @notice thrown when VAI to be minted will go beyond the mintCap threshold\n error VAIMintCapReached();\n /// @notice thrown when fee calculation will result in rounding down to 0 due to stable token amount being a too small number\n error AmountTooSmall();\n\n /**\n * @dev Prevents functions to execute when contract is paused.\n */\n modifier isActive() {\n if (isPaused) revert Paused();\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address stableTokenAddress_, address vaiAddress_) {\n _ensureNonzeroAddress(stableTokenAddress_);\n _ensureNonzeroAddress(vaiAddress_);\n\n uint256 decimals_ = IERC20MetadataUpgradeable(stableTokenAddress_).decimals();\n\n if (decimals_ > 18) {\n revert TooManyDecimals();\n }\n\n ONE_DOLLAR = 10 ** (36 - decimals_); // 1$ scaled to the decimals returned by our Oracle\n STABLE_TOKEN_ADDRESS = stableTokenAddress_;\n VAI = IVAI(vaiAddress_);\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract via Proxy Contract with the required parameters.\n * @param accessControlManager_ The address of the AccessControlManager contract.\n * @param venusTreasury_ The address where fees will be sent.\n * @param oracleAddress_ The address of the ResilientOracle contract.\n * @param feeIn_ The percentage of fees to be applied to a stablecoin -> VAI swap.\n * @param feeOut_ The percentage of fees to be applied to a VAI -> stablecoin swap.\n * @param vaiMintCap_ The cap for the total amount of VAI that can be minted.\n */\n function initialize(\n address accessControlManager_,\n address venusTreasury_,\n address oracleAddress_,\n uint256 feeIn_,\n uint256 feeOut_,\n uint256 vaiMintCap_\n ) external initializer {\n _ensureNonzeroAddress(accessControlManager_);\n _ensureNonzeroAddress(venusTreasury_);\n _ensureNonzeroAddress(oracleAddress_);\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n\n if (feeIn_ >= BASIS_POINTS_DIVISOR || feeOut_ >= BASIS_POINTS_DIVISOR) {\n revert InvalidFee();\n }\n\n feeIn = feeIn_;\n feeOut = feeOut_;\n vaiMintCap = vaiMintCap_;\n venusTreasury = venusTreasury_;\n oracle = ResilientOracleInterface(oracleAddress_);\n }\n\n /*** Swap Functions ***/\n\n /**\n * @notice Swaps VAI for a stable token.\n * @param receiver The address where the stablecoin will be sent.\n * @param stableTknAmount The amount of stable tokens to receive.\n * @return The amount of VAI received and burnt from the sender.\n */\n // @custom:event Emits VAIForStableSwapped event.\n function swapVAIForStable(\n address receiver,\n uint256 stableTknAmount\n ) external isActive nonReentrant returns (uint256) {\n _ensureNonzeroAddress(receiver);\n _ensureNonzeroAmount(stableTknAmount);\n\n // update oracle price and calculate USD value of the stable token amount scaled in 18 decimals\n oracle.updateAssetPrice(STABLE_TOKEN_ADDRESS);\n uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.OUT);\n uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.OUT);\n\n if (VAI.balanceOf(msg.sender) < stableTknAmountUSD + fee) {\n revert NotEnoughVAI();\n }\n if (vaiMinted < stableTknAmountUSD) {\n revert VAIMintedUnderflow();\n }\n\n unchecked {\n vaiMinted -= stableTknAmountUSD;\n }\n\n if (fee != 0) {\n bool success = VAI.transferFrom(msg.sender, venusTreasury, fee);\n if (!success) {\n revert VAITransferFail();\n }\n }\n\n VAI.burn(msg.sender, stableTknAmountUSD);\n IERC20Upgradeable(STABLE_TOKEN_ADDRESS).safeTransfer(receiver, stableTknAmount);\n emit VAIForStableSwapped(stableTknAmountUSD, stableTknAmount, fee);\n return stableTknAmountUSD;\n }\n\n /**\n * @notice Swaps stable tokens for VAI with fees.\n * @dev This function adds support to fee-on-transfer tokens. The actualTransferAmt is calculated, by recording token balance state before and after the transfer.\n * @param receiver The address that will receive the VAI tokens.\n * @param stableTknAmount The amount of stable tokens to be swapped.\n * @return Amount of VAI minted to the sender.\n */\n // @custom:event Emits StableForVAISwapped event.\n function swapStableForVAI(\n address receiver,\n uint256 stableTknAmount\n ) external isActive nonReentrant returns (uint256) {\n _ensureNonzeroAddress(receiver);\n _ensureNonzeroAmount(stableTknAmount);\n // transfer IN, supporting fee-on-transfer tokens\n uint256 balanceBefore = IERC20Upgradeable(STABLE_TOKEN_ADDRESS).balanceOf(address(this));\n IERC20Upgradeable(STABLE_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), stableTknAmount);\n uint256 balanceAfter = IERC20Upgradeable(STABLE_TOKEN_ADDRESS).balanceOf(address(this));\n\n //calculate actual transfered amount (in case of fee-on-transfer tokens)\n uint256 actualTransferAmt = balanceAfter - balanceBefore;\n\n // update oracle price and calculate USD value of the stable token amount scaled in 18 decimals\n oracle.updateAssetPrice(STABLE_TOKEN_ADDRESS);\n uint256 actualTransferAmtInUSD = _previewTokenUSDAmount(actualTransferAmt, FeeDirection.IN);\n\n //calculate feeIn\n uint256 fee = _calculateFee(actualTransferAmtInUSD, FeeDirection.IN);\n uint256 vaiToMint = actualTransferAmtInUSD - fee;\n\n if (vaiMinted + actualTransferAmtInUSD > vaiMintCap) {\n revert VAIMintCapReached();\n }\n unchecked {\n vaiMinted += actualTransferAmtInUSD;\n }\n\n // mint VAI to receiver\n VAI.mint(receiver, vaiToMint);\n\n // mint VAI fee to venus treasury\n if (fee != 0) {\n VAI.mint(venusTreasury, fee);\n }\n\n emit StableForVAISwapped(actualTransferAmt, vaiToMint, fee);\n return vaiToMint;\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Pause the PSM contract.\n * @dev Reverts if the contract is already paused.\n */\n // @custom:event Emits PSMPaused event.\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n if (isPaused) {\n revert AlreadyPaused();\n }\n isPaused = true;\n emit PSMPaused(msg.sender);\n }\n\n /**\n * @notice Resume the PSM contract.\n * @dev Reverts if the contract is not paused.\n */\n // @custom:event Emits PSMResumed event.\n function resume() external {\n _checkAccessAllowed(\"resume()\");\n if (!isPaused) {\n revert NotPaused();\n }\n isPaused = false;\n emit PSMResumed(msg.sender);\n }\n\n /**\n * @notice Set the fee percentage for incoming swaps.\n * @dev Reverts if the new fee percentage is invalid (greater than or equal to BASIS_POINTS_DIVISOR).\n * @param feeIn_ The new fee percentage for incoming swaps.\n */\n // @custom:event Emits FeeInChanged event.\n function setFeeIn(uint256 feeIn_) external {\n _checkAccessAllowed(\"setFeeIn(uint256)\");\n // feeIn = 10000 = 100%\n if (feeIn_ >= BASIS_POINTS_DIVISOR) {\n revert InvalidFee();\n }\n uint256 oldFeeIn = feeIn;\n feeIn = feeIn_;\n emit FeeInChanged(oldFeeIn, feeIn_);\n }\n\n /**\n * @notice Set the fee percentage for outgoing swaps.\n * @dev Reverts if the new fee percentage is invalid (greater than or equal to BASIS_POINTS_DIVISOR).\n * @param feeOut_ The new fee percentage for outgoing swaps.\n */\n // @custom:event Emits FeeOutChanged event.\n function setFeeOut(uint256 feeOut_) external {\n _checkAccessAllowed(\"setFeeOut(uint256)\");\n // feeOut = 10000 = 100%\n if (feeOut_ >= BASIS_POINTS_DIVISOR) {\n revert InvalidFee();\n }\n uint256 oldFeeOut = feeOut;\n feeOut = feeOut_;\n emit FeeOutChanged(oldFeeOut, feeOut_);\n }\n\n /**\n * @dev Set the maximum amount of VAI that can be minted through this contract.\n * @param vaiMintCap_ The new maximum amount of VAI that can be minted.\n */\n // @custom:event Emits VAIMintCapChanged event.\n function setVAIMintCap(uint256 vaiMintCap_) external {\n _checkAccessAllowed(\"setVAIMintCap(uint256)\");\n uint256 oldVAIMintCap = vaiMintCap;\n vaiMintCap = vaiMintCap_;\n emit VAIMintCapChanged(oldVAIMintCap, vaiMintCap_);\n }\n\n /**\n * @notice Set the address of the Venus Treasury contract.\n * @dev Reverts if the new address is zero.\n * @param venusTreasury_ The new address of the Venus Treasury contract.\n */\n // @custom:event Emits VenusTreasuryChanged event.\n function setVenusTreasury(address venusTreasury_) external {\n _checkAccessAllowed(\"setVenusTreasury(address)\");\n _ensureNonzeroAddress(venusTreasury_);\n address oldTreasuryAddress = venusTreasury;\n venusTreasury = venusTreasury_;\n emit VenusTreasuryChanged(oldTreasuryAddress, venusTreasury_);\n }\n\n /**\n * @notice Set the address of the ResilientOracle contract.\n * @dev Reverts if the new address is zero.\n * @param oracleAddress_ The new address of the ResilientOracle contract.\n */\n // @custom:event Emits OracleChanged event.\n function setOracle(address oracleAddress_) external {\n _checkAccessAllowed(\"setOracle(address)\");\n _ensureNonzeroAddress(oracleAddress_);\n address oldOracleAddress = address(oracle);\n oracle = ResilientOracleInterface(oracleAddress_);\n emit OracleChanged(oldOracleAddress, oracleAddress_);\n }\n\n /**\n * @dev Disabling renounceOwnership function.\n */\n function renounceOwnership() public override {}\n\n /*** Helper Functions ***/\n\n /**\n * @notice Calculates the amount of VAI that would be burnt from the user.\n * @dev This calculation might be off with a bit, if the price of the oracle for this asset is not updated in the block this function is invoked.\n * @param stableTknAmount The amount of stable tokens to be received after the swap.\n * @return The amount of VAI that would be taken from the user.\n */\n function previewSwapVAIForStable(uint256 stableTknAmount) external view returns (uint256) {\n _ensureNonzeroAmount(stableTknAmount);\n uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.OUT);\n uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.OUT);\n\n if (vaiMinted < stableTknAmountUSD) {\n revert VAIMintedUnderflow();\n }\n\n return stableTknAmountUSD + fee;\n }\n\n /**\n * @notice Calculates the amount of VAI that would be sent to the receiver.\n * @dev This calculation might be off with a bit, if the price of the oracle for this asset is not updated in the block this function is invoked.\n * @param stableTknAmount The amount of stable tokens provided for the swap.\n * @return The amount of VAI that would be sent to the receiver.\n */\n function previewSwapStableForVAI(uint256 stableTknAmount) external view returns (uint256) {\n _ensureNonzeroAmount(stableTknAmount);\n uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.IN);\n\n //calculate feeIn\n uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.IN);\n uint256 vaiToMint = stableTknAmountUSD - fee;\n\n if (vaiMinted + stableTknAmountUSD > vaiMintCap) {\n revert VAIMintCapReached();\n }\n\n return vaiToMint;\n }\n\n /**\n * @dev Calculates the USD value of the given amount of stable tokens depending on the swap direction.\n * @param amount The amount of stable tokens.\n * @param direction The direction of the swap.\n * @return The USD value of the given amount of stable tokens scaled by 1e18 taking into account the direction of the swap\n */\n function _previewTokenUSDAmount(uint256 amount, FeeDirection direction) internal view returns (uint256) {\n return (amount * _getPriceInUSD(direction)) / MANTISSA_ONE;\n }\n\n /**\n * @notice Get the price of stable token in USD.\n * @dev This function returns either min(1$,oraclePrice) or max(1$,oraclePrice) with a decimal scale (36 - asset_decimals). E.g. for 8 decimal token 1$ will be 1e28.\n * @param direction The direction of the swap: FeeDirection.IN or FeeDirection.OUT.\n * @return The price in USD, adjusted based on the selected direction.\n */\n function _getPriceInUSD(FeeDirection direction) internal view returns (uint256) {\n // get price with a scale = (36 - asset_decimals)\n uint256 price = oracle.getPrice(STABLE_TOKEN_ADDRESS);\n\n if (direction == FeeDirection.IN) {\n // MIN(1, price)\n return price < ONE_DOLLAR ? price : ONE_DOLLAR;\n } else {\n // MAX(1, price)\n return price > ONE_DOLLAR ? price : ONE_DOLLAR;\n }\n }\n\n /**\n * @notice Calculate the fee amount based on the input amount and fee percentage.\n * @dev Reverts if the fee percentage calculation results in rounding down to 0.\n * @param amount The input amount to calculate the fee from.\n * @param direction The direction of the fee: FeeDirection.IN or FeeDirection.OUT.\n * @return The fee amount.\n */\n function _calculateFee(uint256 amount, FeeDirection direction) internal view returns (uint256) {\n uint256 feePercent;\n if (direction == FeeDirection.IN) {\n feePercent = feeIn;\n } else {\n feePercent = feeOut;\n }\n if (feePercent == 0) {\n return 0;\n } else {\n // checking if the percent calculation will result in rounding down to 0\n if (amount * feePercent < BASIS_POINTS_DIVISOR) {\n revert AmountTooSmall();\n }\n return (amount * feePercent) / BASIS_POINTS_DIVISOR;\n }\n }\n\n /**\n * @notice Checks that the address is not the zero address.\n * @param someone The address to check.\n */\n function _ensureNonzeroAddress(address someone) private pure {\n if (someone == address(0)) revert ZeroAddress();\n }\n\n /**\n * @notice Checks that the amount passed as stable tokens is bigger than zero\n * @param amount The amount to validate\n */\n function _ensureNonzeroAmount(uint256 amount) private pure {\n if (amount == 0) revert ZeroAmount();\n }\n}\n" + }, + "contracts/test/BadFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./MockFlashLoanReceiver.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\n\ncontract BadFlashLoanReceiver is MockFlashLoanReceiver {\n constructor(ComptrollerInterface comptroller) MockFlashLoanReceiver(comptroller) {}\n\n function executeOperation(\n VToken[] calldata,\n uint256[] calldata,\n uint256[] calldata,\n address,\n address,\n bytes calldata\n ) external override returns (bool, uint256[] memory) {\n return (false, new uint256[](0));\n }\n}\n" + }, + "contracts/test/BorrowDebtFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./MockFlashLoanReceiver.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\n\ncontract BorrowDebtFlashLoanReceiver is MockFlashLoanReceiver {\n constructor(ComptrollerInterface comptroller) MockFlashLoanReceiver(comptroller) {}\n\n function executeOperation(\n VToken[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata,\n address initiator,\n address onBehalf,\n bytes calldata param\n ) external override returns (bool, uint256[] memory) {\n // 👇 Your custom logic for the flash loan should be implemented here 👇\n /** YOUR CUSTOM LOGIC HERE */\n initiator;\n onBehalf;\n param;\n // 👆 Your custom logic for the flash loan should be implemented above here 👆\n\n uint256[] memory approvedTokens = _approveRepaymentsBorrow(assets, amounts);\n return (true, approvedTokens);\n }\n\n function _approveRepaymentsBorrow(\n VToken[] calldata assets,\n uint256[] calldata amounts\n ) private returns (uint256[] memory) {\n uint256 len = assets.length;\n uint256[] memory approvedTokens = new uint256[](len);\n for (uint256 k = 0; k < len; ++k) {\n uint256 total = amounts[k]; // Intentionally not adding premiums to create debt position\n IERC20NonStandard(assets[k].underlying()).approve(address(assets[k]), total);\n\n approvedTokens[k] = total;\n }\n return approvedTokens;\n }\n}\n" + }, + "contracts/test/ComptrollerHarness.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"./ComptrollerMock.sol\";\nimport \"../Comptroller/Unitroller.sol\";\n\ncontract ComptrollerHarness is ComptrollerMock {\n address internal xvsAddress;\n address internal vXVSAddress;\n uint public blockNumber;\n\n constructor() ComptrollerMock() {}\n\n function setVenusSupplyState(address vToken, uint224 index, uint32 blockNumber_) public {\n venusSupplyState[vToken].index = index;\n venusSupplyState[vToken].block = blockNumber_;\n }\n\n function setVenusBorrowState(address vToken, uint224 index, uint32 blockNumber_) public {\n venusBorrowState[vToken].index = index;\n venusBorrowState[vToken].block = blockNumber_;\n }\n\n function setVenusAccrued(address user, uint userAccrued) public {\n venusAccrued[user] = userAccrued;\n }\n\n function setXVSAddress(address xvsAddress_) public {\n xvsAddress = xvsAddress_;\n }\n\n function setXVSVTokenAddress(address vXVSAddress_) public {\n vXVSAddress = vXVSAddress_;\n }\n\n /**\n * @notice Set the amount of XVS distributed per block\n * @param venusRate_ The amount of XVS wei per block to distribute\n */\n function harnessSetVenusRate(uint venusRate_) public {\n venusRate = venusRate_;\n }\n\n /**\n * @notice Recalculate and update XVS speeds for all XVS markets\n */\n function harnessRefreshVenusSpeeds() public {\n VToken[] memory allMarkets_ = allMarkets;\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusSupplyIndex(address(vToken));\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n }\n\n Exp memory totalUtility = Exp({ mantissa: 0 });\n Exp[] memory utilities = new Exp[](allMarkets_.length);\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n if (venusSpeeds[address(vToken)] > 0) {\n Exp memory assetPrice = Exp({ mantissa: oracle.getUnderlyingPrice(address(vToken)) });\n Exp memory utility = mul_(assetPrice, vToken.totalBorrows());\n utilities[i] = utility;\n totalUtility = add_(totalUtility, utility);\n }\n }\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets[i];\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(venusRate, div_(utilities[i], totalUtility)) : 0;\n setVenusSpeedInternal(vToken, newSpeed, newSpeed);\n }\n }\n\n function setVenusBorrowerIndex(address vToken, address borrower, uint index) public {\n venusBorrowerIndex[vToken][borrower] = index;\n }\n\n function setVenusSupplierIndex(address vToken, address supplier, uint index) public {\n venusSupplierIndex[vToken][supplier] = index;\n }\n\n function harnessDistributeAllBorrowerVenus(\n address vToken,\n address borrower,\n uint marketBorrowIndexMantissa\n ) public {\n distributeBorrowerVenus(vToken, borrower, Exp({ mantissa: marketBorrowIndexMantissa }));\n venusAccrued[borrower] = grantXVSInternal(borrower, venusAccrued[borrower], 0, false);\n }\n\n function harnessDistributeAllSupplierVenus(address vToken, address supplier) public {\n distributeSupplierVenus(vToken, supplier);\n venusAccrued[supplier] = grantXVSInternal(supplier, venusAccrued[supplier], 0, false);\n }\n\n function harnessUpdateVenusBorrowIndex(address vToken, uint marketBorrowIndexMantissa) public {\n updateVenusBorrowIndex(vToken, Exp({ mantissa: marketBorrowIndexMantissa }));\n }\n\n function harnessUpdateVenusSupplyIndex(address vToken) public {\n updateVenusSupplyIndex(vToken);\n }\n\n function harnessDistributeBorrowerVenus(address vToken, address borrower, uint marketBorrowIndexMantissa) public {\n distributeBorrowerVenus(vToken, borrower, Exp({ mantissa: marketBorrowIndexMantissa }));\n }\n\n function harnessDistributeSupplierVenus(address vToken, address supplier) public {\n distributeSupplierVenus(vToken, supplier);\n }\n\n function harnessTransferVenus(address user, uint userAccrued, uint threshold) public returns (uint) {\n if (userAccrued > 0 && userAccrued >= threshold) {\n return grantXVSInternal(user, userAccrued, 0, false);\n }\n return userAccrued;\n }\n\n function harnessAddVenusMarkets(address[] memory vTokens) public {\n for (uint i = 0; i < vTokens.length; i++) {\n // temporarily set venusSpeed to 1 (will be fixed by `harnessRefreshVenusSpeeds`)\n setVenusSpeedInternal(VToken(vTokens[i]), 1, 1);\n }\n }\n\n function harnessSetMintedVAIs(address user, uint amount) public {\n mintedVAIs[user] = amount;\n }\n\n function harnessFastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function getBlockNumber() internal view override returns (uint) {\n return blockNumber;\n }\n\n function getVenusMarkets() public view returns (address[] memory) {\n uint m = allMarkets.length;\n uint n = 0;\n for (uint i = 0; i < m; i++) {\n if (venusSpeeds[address(allMarkets[i])] > 0) {\n n++;\n }\n }\n\n address[] memory venusMarkets = new address[](n);\n uint k = 0;\n for (uint i = 0; i < m; i++) {\n if (venusSpeeds[address(allMarkets[i])] > 0) {\n venusMarkets[k++] = address(allMarkets[i]);\n }\n }\n return venusMarkets;\n }\n\n function harnessSetReleaseStartBlock(uint startBlock) external {\n releaseStartBlock = startBlock;\n }\n\n function harnessAddVtoken(address vToken) external {\n getCorePoolMarket(vToken).isListed = true;\n }\n}\n\ncontract EchoTypesComptroller is UnitrollerAdminStorage {\n function stringy(string memory s) public pure returns (string memory) {\n return s;\n }\n\n function addresses(address a) public pure returns (address) {\n return a;\n }\n\n function booly(bool b) public pure returns (bool) {\n return b;\n }\n\n function listOInts(uint[] memory u) public pure returns (uint[] memory) {\n return u;\n }\n\n function reverty() public pure {\n require(false, \"gotcha sucka\");\n }\n\n function becomeBrains(address payable unitroller) public {\n Unitroller(unitroller)._acceptImplementation();\n }\n}\n" + }, + "contracts/test/ComptrollerMock.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Comptroller/Diamond/facets/MarketFacet.sol\";\nimport \"../Comptroller/Diamond/facets/PolicyFacet.sol\";\nimport \"../Comptroller/Diamond/facets/RewardFacet.sol\";\nimport \"../Comptroller/Diamond/facets/SetterFacet.sol\";\nimport \"../Comptroller/Diamond/facets/FlashLoanFacet.sol\";\nimport \"../Comptroller/Unitroller.sol\";\n\n// This contract contains all methods of Comptroller implementation in different facets at one place for testing purpose\n// This contract does not have diamond functionality(i.e delegate call to facets methods)\ncontract ComptrollerMock is MarketFacet, PolicyFacet, RewardFacet, SetterFacet, FlashLoanFacet {\n constructor() {\n admin = msg.sender;\n }\n\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external override returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/test/ComptrollerMockR1.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Comptroller/legacy/Diamond/facets/MarketFacetR1.sol\";\nimport \"../Comptroller/legacy/Diamond/facets/PolicyFacetR1.sol\";\nimport \"../Comptroller/legacy/Diamond/facets/RewardFacetR1.sol\";\nimport \"../Comptroller/legacy/Diamond/facets/SetterFacetR1.sol\";\nimport \"../Comptroller/Unitroller.sol\";\n\n// This contract contains all methods of Comptroller implementation in different facets at one place for testing purpose\n// This contract does not have diamond functionality(i.e delegate call to facets methods)\ncontract ComptrollerMockR1 is MarketFacetR1, PolicyFacetR1, RewardFacetR1, SetterFacetR1 {\n constructor() {\n admin = msg.sender;\n }\n\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n function _setComptrollerLens(ComptrollerLensInterfaceR1 comptrollerLens_) external override returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/test/ComptrollerScenario.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"./ComptrollerMock.sol\";\n\ncontract ComptrollerScenario is ComptrollerMock {\n uint public blockNumber;\n address public xvsAddress;\n address public vaiAddress;\n\n constructor() ComptrollerMock() {}\n\n function setXVSAddress(address xvsAddress_) public {\n xvsAddress = xvsAddress_;\n }\n\n // function getXVSAddress() public view returns (address) {\n // return xvsAddress;\n // }\n\n function setVAIAddress(address vaiAddress_) public {\n vaiAddress = vaiAddress_;\n }\n\n function getVAIAddress() public view returns (address) {\n return vaiAddress;\n }\n\n function membershipLength(VToken vToken) public view returns (uint) {\n return accountAssets[address(vToken)].length;\n }\n\n function fastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n\n return blockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function getBlockNumber() internal view override returns (uint) {\n return blockNumber;\n }\n\n function getVenusMarkets() public view returns (address[] memory) {\n uint m = allMarkets.length;\n uint n = 0;\n for (uint i = 0; i < m; i++) {\n if (getCorePoolMarket(address(allMarkets[i])).isVenus) {\n n++;\n }\n }\n\n address[] memory venusMarkets = new address[](n);\n uint k = 0;\n for (uint i = 0; i < m; i++) {\n if (getCorePoolMarket(address(allMarkets[i])).isVenus) {\n venusMarkets[k++] = address(allMarkets[i]);\n }\n }\n return venusMarkets;\n }\n\n function unlist(VToken vToken) public {\n getCorePoolMarket(address(vToken)).isListed = false;\n }\n\n /**\n * @notice Recalculate and update XVS speeds for all XVS markets\n */\n function refreshVenusSpeeds() public {\n VToken[] memory allMarkets_ = allMarkets;\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusSupplyIndex(address(vToken));\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n }\n\n Exp memory totalUtility = Exp({ mantissa: 0 });\n Exp[] memory utilities = new Exp[](allMarkets_.length);\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n if (venusSpeeds[address(vToken)] > 0) {\n Exp memory assetPrice = Exp({ mantissa: oracle.getUnderlyingPrice(address(vToken)) });\n Exp memory utility = mul_(assetPrice, vToken.totalBorrows());\n utilities[i] = utility;\n totalUtility = add_(totalUtility, utility);\n }\n }\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets[i];\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(venusRate, div_(utilities[i], totalUtility)) : 0;\n setVenusSpeedInternal(vToken, newSpeed, newSpeed);\n }\n }\n}\n" + }, + "contracts/test/DiamondHarness.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Comptroller/Diamond/Diamond.sol\";\n\ncontract DiamondHarness is Diamond {\n function getFacetAddress(bytes4 sig) public view returns (address) {\n address facet = _selectorToFacetAndPosition[sig].facetAddress;\n require(facet != address(0), \"Diamond: Function does not exist\");\n return facet;\n }\n}\n" + }, + "contracts/test/EvilXDelegator.sol": { + "content": "pragma solidity 0.8.25;\n\nimport { InterestRateModelV8 } from \"../InterestRateModels/InterestRateModelV8.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VTokenInterface, VBep20Interface, VDelegatorInterface } from \"../Tokens/VTokens/VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20Delegator Contract\n * @notice VTokens which wrap an EIP-20 underlying and delegate to an implementation\n * @author Venus\n */\ncontract EvilXDelegator is VTokenInterface, VBep20Interface, VDelegatorInterface {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData The encoded args for becomeImplementation\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(\n implementation_,\n abi.encodeWithSignature(\n \"initialize(address,address,address,uint256,string,string,uint8)\",\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n )\n );\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_, false, becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) public {\n require(msg.sender == admin, \"VBep20Delegator::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature(\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint256 mintAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"mint(uint256)\", mintAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mintBehalf(address receiver, uint256 mintAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"mintBehalf(address,uint256)\", receiver, mintAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint256 redeemTokens) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"redeem(uint256)\", redeemTokens));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"redeemUnderlying(uint256)\", redeemAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrow(uint256 borrowAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrow(uint256)\", borrowAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint256 repayAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"repayBorrow(uint256)\", repayAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"repayBorrowBehalf(address,uint256)\", borrower, repayAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"liquidateBorrow(address,uint256,address)\", borrower, repayAmount, vTokenCollateral)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"transfer(address,uint256)\", dst, amount));\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"transferFrom(address,address,uint256)\", src, dst, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"approve(address,uint256)\", spender, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (-1 means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"allowance(address,address)\", owner, spender)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"balanceOf(address)\", owner));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"balanceOfUnderlying(address)\", owner));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view override returns (uint256, uint256, uint256, uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"getAccountSnapshot(address)\", account)\n );\n return abi.decode(data, (uint256, uint256, uint256, uint256));\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"borrowRatePerBlock()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"supplyRatePerBlock()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"totalBorrowsCurrent()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrowBalanceCurrent(address)\", account));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"borrowBalanceStored(address)\", account)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"exchangeRateCurrent()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() public view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"exchangeRateStored()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"getCash()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves.\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n function accrueInterest() public override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"accrueInterest()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"seize(address,address,uint256)\", liquidator, borrower, seizeTokens)\n );\n return abi.decode(data, (uint256));\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setPendingAdmin(address)\", newPendingAdmin)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setComptroller(address)\", newComptroller)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setReserveFactor(uint256 newReserveFactorMantissa) external override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setReserveFactor(uint256)\", newReserveFactorMantissa)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_acceptAdmin()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from admin\n * @param addAmount Amount of reserves to add\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint256 addAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_addReserves(uint256)\", addAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _reduceReserves(uint256 reduceAmount) external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_reduceReserves(uint256)\", reduceAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Opens a debt position for the borrower as part of flash loan repayment\n * @dev This function is specifically called during flash loan operations when the repayment\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\n * and updates the borrower's balance. It also emits a Borrow event and calls the\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\n * if the market's block number is not current.\n * @param borrower The address of the borrower who will have the debt position created\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\n */\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"flashLoanDebtPosition(address,uint256)\", borrower, borrowAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setInterestRateModel(address)\", newInterestRateModel)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize())\n }\n }\n return returnData;\n }\n\n /**\n * @notice Delegates execution to the implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToImplementation(bytes memory data) public returns (bytes memory) {\n return delegateTo(implementation, data);\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n (bool success, bytes memory returnData) = address(this).staticcall(\n abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data)\n );\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize())\n }\n }\n return abi.decode(returnData, (bytes));\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n */\n fallback() external {\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/test/EvilXToken.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Tokens/VTokens/VBep20Immutable.sol\";\nimport \"../Tokens/VTokens/VBep20Delegator.sol\";\nimport \"../Tokens/VTokens/VBep20Delegate.sol\";\nimport \"./ComptrollerScenario.sol\";\nimport \"../Comptroller/ComptrollerInterface.sol\";\n\ncontract VBep20Scenario is VBep20Immutable {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\n// doTransferOut method of this token supposed to be compromised and contians malicious code which\n// can be used by attacker to compromise the protocol working.\ncontract EvilXToken is VBep20Delegate {\n event Log(string x, address y);\n event Log(string x, uint y);\n event LogLiquidity(uint liquidity);\n\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n address public comptrollerAddress;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function setComptrollerAddress(address _comptrollerAddress) external {\n comptrollerAddress = _comptrollerAddress;\n }\n\n function exchangeRateStoredInternal() internal view override returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function doTransferOut(address payable to, uint amount) internal override {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n super.doTransferOut(to, amount);\n\n // Checking the Liquidity of the user after the tranfer.\n // solhint-disable-next-line no-unused-vars\n (uint errorCode, uint liquidity, uint shortfall) = ComptrollerInterface(comptrollerAddress).getAccountLiquidity(\n msg.sender\n );\n emit LogLiquidity(liquidity);\n return;\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessIncrementTotalBorrows(uint addtlBorrow_) public {\n totalBorrows = totalBorrows + addtlBorrow_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount, true);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModelV8(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n\n function harnessSetInternalCash(uint256 _internalCash) public {\n internalCash = _internalCash;\n }\n}\n" + }, + "contracts/test/FlashLoanReceiverBase.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IFlashLoanReceiver } from \"../FlashLoan/interfaces/IFlashLoanReceiver.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\n\n/// @title FlashLoanReceiverBase\n/// @notice A base contract for implementing flashLoan receiver logic.\n/// @dev This abstract contract provides the necessary structure for inheriting contracts to implement the `IFlashLoanReceiver` interface.\n/// It stores a reference to the Comptroller contract, which manages various aspects of the protocol.\nabstract contract FlashLoanReceiverBase is IFlashLoanReceiver {\n /// @notice The Comptroller contract that governs the protocol.\n /// @dev This variable stores the address of the Comptroller contract, which cannot be changed after deployment.\n ComptrollerInterface public COMPTROLLER;\n\n /**\n * @notice Constructor to initialize the base contract with the Comptroller address.\n * @param comptroller_ The address of the Comptroller contract that oversees the protocol.\n */\n constructor(ComptrollerInterface comptroller_) {\n COMPTROLLER = comptroller_;\n }\n}\n" + }, + "contracts/test/imports.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n// Force Hardhat to compile DeviationBoundedOracle from node_modules so that\n// @openzeppelin/hardhat-upgrades can run storage-layout validation.\nimport { DeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/DeviationBoundedOracle.sol\";\n" + }, + "contracts/test/InsufficientRepaymentFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./MockFlashLoanReceiver.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\n\ncontract InsufficientRepaymentFlashLoanReceiver is MockFlashLoanReceiver {\n constructor(ComptrollerInterface comptroller) MockFlashLoanReceiver(comptroller) {}\n\n function executeOperation(\n VToken[] calldata assets,\n uint256[] calldata,\n uint256[] calldata premiums,\n address initiator,\n address onBehalf,\n bytes calldata param\n ) external override returns (bool, uint256[] memory) {\n initiator;\n onBehalf;\n param;\n\n uint256[] memory approvedTokens = _approveInsufficientRepayments(assets, premiums);\n return (true, approvedTokens);\n }\n\n function _approveInsufficientRepayments(\n VToken[] calldata assets,\n uint256[] calldata premiums\n ) private returns (uint256[] memory) {\n uint256 len = assets.length;\n uint256[] memory approvedTokens = new uint256[](len);\n\n for (uint256 k = 0; k < len; ++k) {\n // Approve only half of the premium (fee) - intentionally insufficient\n uint256 insufficientAmount = premiums[k] / 2;\n IERC20NonStandard(assets[k].underlying()).approve(address(assets[k]), insufficientAmount);\n\n approvedTokens[k] = insufficientAmount;\n }\n return approvedTokens;\n }\n}\n" + }, + "contracts/test/LiquidatorHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../Liquidator/Liquidator.sol\";\nimport \"@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol\";\n\ncontract LiquidatorHarness is Liquidator {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address comptroller_, address payable vBnb_, address wBnb_) Liquidator(comptroller_, vBnb_, wBnb_) {}\n\n function initialize(\n uint256 liquidationIncentiveMantissa_,\n address accessControlManager_,\n address protocolShareReserve_\n ) external override initializer {\n __Liquidator_init(liquidationIncentiveMantissa_, accessControlManager_, protocolShareReserve_);\n }\n\n event DistributeLiquidationIncentive(uint256 seizeTokensForTreasury, uint256 seizeTokensForLiquidator);\n\n /// @dev Splits the received vTokens between the liquidator and treasury.\n function distributeLiquidationIncentive(\n address borrower,\n IVToken vTokenCollateral,\n uint256 siezedAmount\n ) public returns (uint256 ours, uint256 theirs) {\n (ours, theirs) = super._distributeLiquidationIncentive(borrower, vTokenCollateral, siezedAmount);\n emit DistributeLiquidationIncentive(ours, theirs);\n return (ours, theirs);\n }\n\n /// @dev Computes the amounts that would go to treasury and to the liquidator.\n function splitLiquidationIncentive(\n address borrower,\n address vTokenCollateral,\n uint256 seizedAmount\n ) public view returns (uint256 ours, uint256 theirs) {\n return super._splitLiquidationIncentive(borrower, vTokenCollateral, seizedAmount);\n }\n}\n" + }, + "contracts/test/MockFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { FlashLoanReceiverBase } from \"./FlashLoanReceiverBase.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { IERC20NonStandard } from \"../Tokens/test/IERC20NonStandard.sol\";\n\n/// @title MockFlashLoanReceiver\n/// @notice A mock implementation of a flashLoan receiver contract that interacts with the Comptroller to request and handle flash loans.\n/// @dev This contract extends `FlashLoanReceiverBase` and implements custom logic to request flash loans and repay them.\ncontract MockFlashLoanReceiver is FlashLoanReceiverBase {\n /**\n * @notice Constructor to initialize the flashLoan receiver with the Comptroller contract.\n * @param comptroller The address of the Comptroller contract used to request flash loans.\n */\n constructor(ComptrollerInterface comptroller) FlashLoanReceiverBase(comptroller) {}\n\n /**\n * @notice Requests a flash loan from the Comptroller contract.\n * @dev This function calls the `executeFlashLoan` function from the Comptroller to initiate a flash loan.\n * @param assets An array of VToken contracts that support flash loans.\n * @param amounts An array of amounts to borrow in the flash loan for each corresponding asset.\n * @param receiver The address of the contract that will receive the flashLoan and execute the operation.\n * @param param Additional encoded parameters passed with the flash loan.\n */\n function requestFlashLoan(\n VToken[] calldata assets,\n uint256[] calldata amounts,\n address payable receiver,\n bytes calldata param\n ) external {\n // Request the flashLoan from the Comptroller contract\n COMPTROLLER.executeFlashLoan(payable(msg.sender), receiver, assets, amounts, param);\n }\n\n /**\n * @notice Executes custom logic after receiving the flash loan.\n * @dev This function is called by the Comptroller contract as part of the flashLoan process.\n * It must repay the loan amount plus the premium for each borrowed asset.\n * @param assets The VToken contracts for the flash-borrowed assets.\n * @param amounts The amounts of each asset borrowed.\n * @param premiums The fees for each flash-borrowed asset.\n * @param initiator The address that initiated the flash loan.\n * @param onBehalf The address of the user whose debt position will be used for the flashLoan.\n * @param param Additional encoded parameters passed with the flash loan.\n * @return True if the operation succeeds and the debt plus premium is repaid, false otherwise.\n */\n function executeOperation(\n VToken[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata premiums,\n address initiator,\n address onBehalf,\n bytes calldata param\n ) external virtual returns (bool, uint256[] memory) {\n // 👇 Your custom logic for the flash loan should be implemented here 👇\n /** YOUR CUSTOM LOGIC HERE */\n initiator;\n onBehalf;\n param;\n // 👆 Your custom logic for the flash loan should be implemented above here 👆\n\n uint256[] memory approvedTokens = _approveRepayments(assets, amounts, premiums);\n return (true, approvedTokens);\n }\n\n function _approveRepayments(\n VToken[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata premiums\n ) private returns (uint256[] memory) {\n uint256 len = assets.length;\n uint256[] memory approvedTokens = new uint256[](len);\n for (uint256 k = 0; k < len; ++k) {\n uint256 total = amounts[k] + premiums[k];\n IERC20NonStandard(assets[k].underlying()).approve(address(assets[k]), total);\n approvedTokens[k] = total;\n }\n return approvedTokens;\n }\n}\n" + }, + "contracts/test/MockProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\ninterface IIncomeDestination {\n function updateAssetsState(address comptroller, address asset) external;\n}\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n\ninterface IPrime is IIncomeDestination {\n function accrueInterest(address vToken) external;\n\n function vTokenForAsset(address asset) external view returns (address);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n\ninterface IPoolRegistry {\n /// @notice Get VToken in the Pool for an Asset\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\n}\n\ninterface IMockProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n FLASHLOAN\n }\n\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\n}\n\ninterface IComptroller {\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n\nerror InvalidAddress();\nerror UnsupportedAsset();\nerror InvalidTotalPercentage();\nerror InvalidMaxLoopsLimit();\n\n/**\n * @title MaxLoopsLimitHelper\n * @author Venus\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\n */\nabstract contract MaxLoopsLimitHelper {\n // Limit for the loops to avoid the DOS\n uint256 public maxLoopsLimit;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when max loops limit is set\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\n\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function _setMaxLoopsLimit(uint256 limit) internal {\n require(limit > maxLoopsLimit, \"Comptroller: Invalid maxLoopsLimit\");\n\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\n maxLoopsLimit = limit;\n\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\n }\n\n /**\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\n * @param len Length of the loops iterate\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\n */\n function _ensureMaxLoops(uint256 len) internal view {\n if (len > maxLoopsLimit) {\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\n }\n }\n}\n\ncontract MockProtocolShareReserve is\n AccessControlledV8,\n ReentrancyGuardUpgradeable,\n MaxLoopsLimitHelper,\n IMockProtocolShareReserve\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice protocol income is categorized into two schemas.\n /// The first schema is the default one\n /// The second schema is for spread income from prime markets in core protocol\n enum Schema {\n DEFAULT,\n SPREAD_PRIME_CORE\n }\n\n struct DistributionConfig {\n Schema schema;\n /// @dev percenatge is represented without any scale\n uint256 percentage;\n address destination;\n }\n\n /// @notice address of core pool comptroller contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n /// @notice address of WBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WBNB;\n\n /// @notice address of vBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vBNB;\n\n /// @notice address of Prime contract\n address public prime;\n\n /// @notice address of pool registry contract\n address public poolRegistry;\n\n uint256 private constant MAX_PERCENT = 100;\n\n /// @notice comptroller => asset => schema => balance\n mapping(address => mapping(address => mapping(Schema => uint256))) public assetsReserves;\n\n /// @notice asset => balance\n mapping(address => uint256) public totalAssetReserve;\n\n /// @notice configuration for different income distribution targets\n DistributionConfig[] public distributionTargets;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when prime address is updated\n event PrimeUpdated(address indexed oldPrime, address indexed newPrime);\n\n /// @notice Event emitted after the updation of the assets reserves.\n event AssetsReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n uint256 amount,\n IncomeType incomeType,\n Schema schema\n );\n\n /// @notice Event emitted when an asset is released to a target\n event AssetReleased(\n address indexed destination,\n address indexed asset,\n Schema schema,\n uint256 percent,\n uint256 amount\n );\n\n /// @notice Event emitted when asset reserves state is updated\n event ReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n Schema schema,\n uint256 oldBalance,\n uint256 newBalance\n );\n\n /// @notice Event emitted when distribution configuration is updated\n event DistributionConfigUpdated(\n address indexed destination,\n uint256 oldPercentage,\n uint256 newPercentage,\n Schema schema\n );\n\n /// @notice Event emitted when distribution configuration is added\n event DistributionConfigAdded(address indexed destination, uint256 percentage, Schema schema);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _corePoolComptroller, address _wbnb, address _vbnb) {\n if (_corePoolComptroller == address(0)) revert InvalidAddress();\n if (_wbnb == address(0)) revert InvalidAddress();\n if (_vbnb == address(0)) revert InvalidAddress();\n\n CORE_POOL_COMPTROLLER = _corePoolComptroller;\n WBNB = _wbnb;\n vBNB = _vbnb;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the deployer to owner.\n * @param _accessControlManager The address of ACM contract\n * @param _loopsLimit Limit for the loops in the contract to avoid DOS\n */\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\n __AccessControlled_init(_accessControlManager);\n __ReentrancyGuard_init();\n _setMaxLoopsLimit(_loopsLimit);\n }\n\n /**\n * @dev Pool registry setter.\n * @param _poolRegistry Address of the pool registry\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\n if (_poolRegistry == address(0)) revert InvalidAddress();\n emit PoolRegistryUpdated(poolRegistry, _poolRegistry);\n poolRegistry = _poolRegistry;\n }\n\n /**\n * @dev Prime contract address setter.\n * @param _prime Address of the prime contract\n */\n function setPrime(address _prime) external onlyOwner {\n if (_prime == address(0)) revert InvalidAddress();\n emit PrimeUpdated(prime, _prime);\n prime = _prime;\n }\n\n /**\n * @dev Add or update destination targets based on destination address\n * @param configs configurations of the destinations.\n */\n function addOrUpdateDistributionConfigs(DistributionConfig[] memory configs) external nonReentrant {\n _checkAccessAllowed(\"addOrUpdateDistributionConfigs(DistributionConfig[])\");\n\n //we need to accrue and release funds to prime before updating the distribution configuration\n //because prime relies on getUnreleasedFunds and its return value may change after config update\n _accrueAndReleaseFundsToPrime();\n for (uint256 i; i < configs.length; ) {\n DistributionConfig memory _config = configs[i];\n require(_config.destination != address(0), \"ProtocolShareReserve: Destination address invalid\");\n\n bool updated = false;\n for (uint256 j = 0; j < distributionTargets.length; ) {\n DistributionConfig storage config = distributionTargets[j];\n\n if (_config.schema == config.schema && config.destination == _config.destination) {\n emit DistributionConfigUpdated(\n _config.destination,\n config.percentage,\n _config.percentage,\n _config.schema\n );\n config.percentage = _config.percentage;\n updated = true;\n break;\n }\n\n unchecked {\n ++j;\n }\n }\n\n if (!updated) {\n distributionTargets.push(_config);\n emit DistributionConfigAdded(_config.destination, _config.percentage, _config.schema);\n }\n\n unchecked {\n ++i;\n }\n }\n\n _ensurePercentages();\n _ensureMaxLoops(distributionTargets.length);\n }\n\n /**\n * @dev Release funds\n * @param comptroller the comptroller address of the pool\n * @param assets assets to be released to distribution targets\n */\n function releaseFunds(address comptroller, address[] memory assets) external nonReentrant {\n _accruePrimeInterest();\n\n for (uint256 i; i < assets.length; ) {\n _releaseFund(comptroller, assets[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Used to find out the amount of funds that's going to be released when release funds is called.\n * @param comptroller the comptroller address of the pool\n * @param schema the schema of the distribution target\n * @param destination the destination address of the distribution target\n * @param asset the asset address which will be released\n */\n function getUnreleasedFunds(\n address comptroller,\n Schema schema,\n address destination,\n address asset\n ) external view returns (uint256) {\n for (uint256 i; i < distributionTargets.length; ) {\n DistributionConfig storage _config = distributionTargets[i];\n if (_config.schema == schema && _config.destination == destination) {\n uint256 total = assetsReserves[comptroller][asset][schema];\n return (total * _config.percentage) / MAX_PERCENT;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Returns the total number of distribution targets\n */\n function totalDistributions() external view returns (uint256) {\n return distributionTargets.length;\n }\n\n /**\n * @dev Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\n * @param comptroller Comptroller address (pool)\n * @param asset Asset address.\n * @param incomeType type of income\n */\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) public override(IMockProtocolShareReserve) nonReentrant {\n if (!IComptroller(comptroller).isComptroller()) revert InvalidAddress();\n if (asset == address(0)) revert InvalidAddress();\n if (\n comptroller != CORE_POOL_COMPTROLLER &&\n IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)\n ) revert InvalidAddress();\n\n Schema schema = getSchema(comptroller, asset, incomeType);\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = totalAssetReserve[asset];\n\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n\n assetsReserves[comptroller][asset][schema] += balanceDifference;\n totalAssetReserve[asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference, incomeType, schema);\n }\n }\n\n /**\n * @dev Fetches the list of prime markets and then accrues interest and\n * releases the funds to prime for each market\n */\n function _accrueAndReleaseFundsToPrime() internal {\n address[] memory markets = IPrime(prime).getAllMarkets();\n for (uint256 i; i < markets.length; ) {\n address market = markets[i];\n IPrime(prime).accrueInterest(market);\n _releaseFund(CORE_POOL_COMPTROLLER, _getUnderlying(market));\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Fetches the list of prime markets and then accrues interest\n * to prime for each market\n */\n function _accruePrimeInterest() internal {\n // address[] memory markets = IPrime(prime).getAllMarkets();\n address[] memory markets = IPrime(prime).getAllMarkets();\n\n for (uint256 i; i < markets.length; ) {\n address market = markets[i];\n IPrime(prime).accrueInterest(market);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev asset from a particular pool to be release to distribution targets\n * @param comptroller Comptroller address(pool)\n * @param asset Asset address.\n */\n function _releaseFund(address comptroller, address asset) internal {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint256[] memory schemaBalances = new uint256[](totalSchemas);\n uint256 totalBalance;\n for (uint256 schemaValue; schemaValue < totalSchemas; ) {\n schemaBalances[schemaValue] = assetsReserves[comptroller][asset][Schema(schemaValue)];\n totalBalance += schemaBalances[schemaValue];\n\n unchecked {\n ++schemaValue;\n }\n }\n\n if (totalBalance == 0) {\n return;\n }\n\n uint256[] memory totalTransferAmounts = new uint256[](totalSchemas);\n for (uint256 i; i < distributionTargets.length; ) {\n DistributionConfig memory _config = distributionTargets[i];\n\n uint256 transferAmount = (schemaBalances[uint256(_config.schema)] * _config.percentage) / MAX_PERCENT;\n totalTransferAmounts[uint256(_config.schema)] += transferAmount;\n\n IERC20Upgradeable(asset).safeTransfer(_config.destination, transferAmount);\n IIncomeDestination(_config.destination).updateAssetsState(comptroller, asset);\n\n emit AssetReleased(_config.destination, asset, _config.schema, _config.percentage, transferAmount);\n\n unchecked {\n ++i;\n }\n }\n\n uint256[] memory newSchemaBalances = new uint256[](totalSchemas);\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n newSchemaBalances[schemaValue] = schemaBalances[schemaValue] - totalTransferAmounts[schemaValue];\n assetsReserves[comptroller][asset][Schema(schemaValue)] = newSchemaBalances[schemaValue];\n totalAssetReserve[asset] = totalAssetReserve[asset] - totalTransferAmounts[schemaValue];\n\n emit ReservesUpdated(\n comptroller,\n asset,\n Schema(schemaValue),\n schemaBalances[schemaValue],\n newSchemaBalances[schemaValue]\n );\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the schema based on comptroller, asset and income type\n * @param comptroller Comptroller address(pool)\n * @param asset Asset address.\n * @param incomeType type of income\n * @return schema schema for distribution\n */\n function getSchema(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) internal view returns (Schema schema) {\n schema = Schema.DEFAULT;\n address vToken = IPrime(prime).vTokenForAsset(asset);\n if (vToken != address(0) && comptroller == CORE_POOL_COMPTROLLER && incomeType == IncomeType.SPREAD) {\n schema = Schema.SPREAD_PRIME_CORE;\n }\n }\n\n function _ensurePercentages() internal view {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint256[] memory totalPercentages = new uint256[](totalSchemas);\n\n for (uint256 i; i < distributionTargets.length; ) {\n DistributionConfig memory config = distributionTargets[i];\n totalPercentages[uint256(config.schema)] += config.percentage;\n\n unchecked {\n ++i;\n }\n }\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n if (totalPercentages[schemaValue] != MAX_PERCENT && totalPercentages[schemaValue] != 0)\n revert InvalidTotalPercentage();\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the underlying asset address for the vToken\n * @param vToken vToken address\n * @return asset address of asset\n */\n function _getUnderlying(address vToken) internal view returns (address) {\n if (vToken == vBNB) {\n return WBNB;\n } else {\n return IVToken(vToken).underlying();\n }\n }\n}\n" + }, + "contracts/test/MockVBNB.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Tokens/VTokens/VToken.sol\";\n\n/**\n * @title Venus's vBNB Contract\n * @notice vToken which wraps BNB\n * @author Venus\n */\ncontract MockVBNB is VToken {\n /**\n * @notice Construct a new vBNB money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n */\n constructor(\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Send BNB to VBNB to mint\n */\n receive() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Reverts upon any failure\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits Mint event\n function mint() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @dev Reverts upon any failure\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrow() external payable {\n (uint err, ) = repayBorrowInternal(msg.value);\n requireNoError(err, \"repayBorrow failed\");\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @dev Reverts upon any failure\n * @param borrower The account with the debt being payed off\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrowBehalf(address borrower) external payable {\n (uint err, ) = repayBorrowBehalfInternal(borrower, msg.value);\n requireNoError(err, \"repayBorrowBehalf failed\");\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @dev Reverts upon any failure\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n */\n // @custom:event Emit LiquidateBorrow event on success\n function liquidateBorrow(address borrower, VToken vTokenCollateral) external payable {\n (uint err, ) = liquidateBorrowInternal(borrower, msg.value, vTokenCollateral);\n requireNoError(err, \"liquidateBorrow failed\");\n }\n\n function setTotalReserves(uint totalReserves_) external payable {\n totalReserves = totalReserves_;\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Perform the actual transfer in, which is a no-op\n * @param from Address sending the BNB\n * @param amount Amount of BNB being sent\n * @return The actual amount of BNB transferred\n */\n function doTransferIn(address from, uint amount) internal override returns (uint) {\n // Sanity checks\n require(msg.sender == from, \"sender mismatch\");\n require(msg.value == amount, \"value mismatch\");\n return amount;\n }\n\n function doTransferOut(address payable to, uint amount) internal override {\n /* Send the BNB, with minimal gas and revert on failure */\n to.transfer(amount);\n }\n\n /**\n * @notice Gets balance of this contract in terms of BNB, before this message\n * @dev This excludes the value of the current message, if any\n * @return The quantity of BNB owned by this contract\n */\n function getCashPrior() internal view override returns (uint) {\n (MathError err, uint startingBalance) = subUInt(address(this).balance, msg.value);\n require(err == MathError.NO_ERROR, \"cash prior math error\");\n return startingBalance;\n }\n\n function requireNoError(uint errCode, string memory message) internal pure {\n if (errCode == uint(Error.NO_ERROR)) {\n return;\n }\n\n bytes memory fullMessage = new bytes(bytes(message).length + 5);\n uint i;\n\n for (i = 0; i < bytes(message).length; i++) {\n fullMessage[i] = bytes(message)[i];\n }\n\n fullMessage[i + 0] = bytes1(uint8(32));\n fullMessage[i + 1] = bytes1(uint8(40));\n fullMessage[i + 2] = bytes1(uint8(48 + (errCode / 10)));\n fullMessage[i + 3] = bytes1(uint8(48 + (errCode % 10)));\n fullMessage[i + 4] = bytes1(uint8(41));\n\n require(errCode == uint(Error.NO_ERROR), string(fullMessage));\n }\n\n /**\n * @dev Function to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n */\n function getBlockNumber() internal view returns (uint) {\n return block.number;\n }\n\n /**\n * @notice Reduces reserves by transferring to admin\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReservesFresh(uint reduceAmount) internal override returns (uint) {\n // totalReserves - reduceAmount\n uint totalReservesNew;\n\n // Check caller is admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.REDUCE_RESERVES_ADMIN_CHECK);\n }\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != getBlockNumber()) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (getCashPrior() < reduceAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew = totalReserves - reduceAmount;\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n doTransferOut(admin, reduceAmount);\n\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesReduced event\n function _reduceReserves(uint reduceAmount) external override nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\n return _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n // @custom:event Emits AccrueInterest event\n function accrueInterest() public override returns (uint) {\n /* Remember the initial block number */\n uint currentBlockNumber = getBlockNumber();\n uint accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return uint(Error.NO_ERROR);\n }\n\n /* Read the previous values out of storage */\n uint cashPrior = getCashPrior();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\n uint borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n require(borrowRateMantissa <= borrowRateMaxMantissa, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n require(mathErr == MathError.NO_ERROR, \"could not calculate block delta\");\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor;\n uint interestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return uint(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/test/PrimeScenario.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../Tokens/Prime/Prime.sol\";\n\ncontract PrimeScenario is Prime {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wbnb,\n address _vbnb,\n uint256 _blocksPerYear,\n uint256 _stakingPeriod,\n uint256 _minimumStakedXVS,\n uint256 _maximumXVSCap,\n bool _timeBased\n ) Prime(_wbnb, _vbnb, _blocksPerYear, _stakingPeriod, _minimumStakedXVS, _maximumXVSCap, _timeBased) {}\n\n function calculateScore(uint256 xvs, uint256 capital) external view returns (uint256) {\n return Scores._calculateScore(xvs, capital, alphaNumerator, alphaDenominator);\n }\n\n function setPLP(address plp) external {\n primeLiquidityProvider = plp;\n }\n\n function mintForUser(address user) external {\n tokens[user] = Token(true, true);\n }\n\n function burnForUser(address user) external {\n tokens[user] = Token(false, false);\n }\n}\n" + }, + "contracts/test/SimplePriceOracle.sol": { + "content": "pragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport \"../Tokens/VTokens/VBep20.sol\";\n\ncontract SimplePriceOracle is ResilientOracleInterface {\n mapping(address => uint) internal prices;\n event PricePosted(address asset, uint previousPriceMantissa, uint requestedPriceMantissa, uint newPriceMantissa);\n\n function getUnderlyingPrice(address vToken) public view returns (uint) {\n string memory symbol = VToken(vToken).symbol();\n if (compareStrings(symbol, \"vBNB\")) {\n return 1e18;\n } else if (compareStrings(symbol, \"VAI\")) {\n return prices[address(vToken)];\n } else {\n return prices[address(VBep20(address(vToken)).underlying())];\n }\n }\n\n function getPrice(address asset) external view returns (uint256) {\n return prices[asset];\n }\n\n function updatePrice(address vToken) external {}\n\n function updateAssetPrice(address asset) external {}\n\n function setUnderlyingPrice(VToken vToken, uint underlyingPriceMantissa) public {\n address asset = address(VBep20(address(vToken)).underlying());\n emit PricePosted(asset, prices[asset], underlyingPriceMantissa, underlyingPriceMantissa);\n prices[asset] = underlyingPriceMantissa;\n }\n\n function setDirectPrice(address asset, uint price) public {\n emit PricePosted(asset, prices[asset], price, price);\n prices[asset] = price;\n }\n\n // v1 price oracle interface for use as backing of proxy\n function assetPrices(address asset) external view returns (uint) {\n return prices[asset];\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}\n" + }, + "contracts/test/VAIControllerHarness.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Tokens/VAI/VAIController.sol\";\n\ncontract VAIControllerHarness is VAIController {\n uint public blockNumber;\n uint public blocksPerYear;\n\n constructor() VAIController() {\n admin = msg.sender;\n }\n\n function setVenusVAIState(uint224 index, uint32 blockNumber_) public {\n venusVAIState.index = index;\n venusVAIState.block = blockNumber_;\n }\n\n function setVAIAddress(address vaiAddress_) public {\n vai = vaiAddress_;\n }\n\n function getVAIAddress() public view override returns (address) {\n return vai;\n }\n\n function harnessRepayVAIFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayVAIFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateVAIFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateVAIFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessFastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function setBlocksPerYear(uint number) public {\n blocksPerYear = number;\n }\n\n function getBlockNumber() internal view override returns (uint) {\n return blockNumber;\n }\n\n function getBlocksPerYear() public view override returns (uint) {\n return blocksPerYear;\n }\n}\n" + }, + "contracts/test/VBep20Harness.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Tokens/VTokens/VBep20Immutable.sol\";\nimport \"../Tokens/VTokens/VBep20Delegator.sol\";\nimport \"../Tokens/VTokens/VBep20Delegate.sol\";\nimport \"./ComptrollerScenario.sol\";\n\ncontract VBep20Harness is VBep20Immutable {\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function doTransferOut(address payable to, uint amount) internal override {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n return super.doTransferOut(to, amount);\n }\n\n function exchangeRateStoredInternal() internal view override returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount, true);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModelV8(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n\n function harnessSetInternalCash(uint256 _internalCash) public {\n internalCash = _internalCash;\n }\n}\n\ncontract VBep20Scenario is VBep20Immutable {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\ncontract VEvil is VBep20Scenario {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n VBep20Scenario(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function evilSeize(VToken treasure, address liquidator, address borrower, uint seizeTokens) public returns (uint) {\n return treasure.seize(liquidator, borrower, seizeTokens);\n }\n}\n\nabstract contract VBep20DelegatorScenario is VBep20Delegator {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n )\n VBep20Delegator(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n implementation_,\n becomeImplementationData\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n}\n\ncontract VBep20DelegateHarness is VBep20Delegate {\n event Log(string x, address y);\n event Log(string x, uint y);\n\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function exchangeRateStoredInternal() internal view override returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function doTransferOut(address payable to, uint amount) internal override {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n return super.doTransferOut(to, amount);\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessIncrementTotalBorrows(uint addtlBorrow_) public {\n totalBorrows = totalBorrows + addtlBorrow_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount, true);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModelV8(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n\n function harnessSetInternalCash(uint256 _internalCash) public {\n internalCash = _internalCash;\n }\n}\n\ncontract VBep20DelegateScenario is VBep20Delegate {\n constructor() {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\ncontract VBep20DelegateScenarioExtra is VBep20DelegateScenario {\n function iHaveSpoken() public pure returns (string memory) {\n return \"i have spoken\";\n }\n\n function itIsTheWay() public {\n admin = payable(address(1)); // make a change to test effect\n }\n\n function babyYoda() public pure {\n revert(\"protect the baby\");\n }\n}\n" + }, + "contracts/test/VBep20MockDelegate.sol": { + "content": "pragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { InterestRateModelV8 } from \"../InterestRateModels/InterestRateModelV8.sol\";\nimport { VBep20Interface, VTokenInterface } from \"../Tokens/VTokens/VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20 Contract\n * @notice VTokens which wrap an EIP-20 underlying\n * @author Venus\n */\ncontract VBep20MockDelegate is VToken, VBep20Interface {\n using SafeERC20 for IERC20;\n\n uint internal blockNumber = 100000;\n\n /**\n * @notice Initialize the new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n // VToken initialize does the bulk of the work\n super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20(underlying).totalSupply();\n }\n\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) public {\n // Shh -- currently unused\n data;\n\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _becomeImplementation\");\n }\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() public {\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _resignImplementation\");\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint mintAmount) external returns (uint) {\n (uint err, ) = mintInternal(mintAmount);\n return err;\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver the account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n (uint err, ) = mintBehalfInternal(receiver, mintAmount);\n return err;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\n return err;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n (uint err, ) = liquidateBorrowInternal(borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount fo underlying token to add as reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint addAmount) external returns (uint) {\n return _addReservesInternal(addAmount);\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets the tracked internal cash balance of this contract\n * @dev Returns `internalCash` rather than the actual token balance, making it immune to donation attacks.\n * @return The internally tracked cash balance of underlying tokens\n */\n function getCashPrior() internal view override returns (uint) {\n return internalCash;\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\n * This will revert due to insufficient balance or insufficient allowance.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n * Increments `internalCash` by the actual amount received.\n *\n * Note: This wrapper safely handles non-standard BEP-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferIn(address from, uint amount) internal override returns (uint) {\n IERC20 token = IERC20(underlying);\n uint balanceBefore = IERC20(underlying).balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n // Calculate the amount that was *actually* transferred\n uint balanceAfter = IERC20(underlying).balanceOf(address(this));\n uint actualAmount = balanceAfter - balanceBefore;\n internalCash += actualAmount;\n return actualAmount;\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\n * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to\n * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified\n * it is >= amount, this should not revert in normal conditions.\n * Decrements `internalCash` by `amount` before transferring.\n *\n * Note: This wrapper safely handles non-standard BEP-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferOut(address payable to, uint amount) internal override {\n internalCash -= amount;\n IERC20 token = IERC20(underlying);\n token.safeTransfer(to, amount);\n }\n\n function harnessSetInternalCash(uint256 _internalCash) public {\n internalCash = _internalCash;\n }\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/InterfaceComptroller.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface InterfaceComptroller {\n function markets(address) external view returns (bool);\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/**\n * @title PoolRegistryInterface\n * @author Venus\n * @notice Interface implemented by `PoolRegistry`.\n */\ninterface PoolRegistryInterface {\n /**\n * @notice Struct for a Venus interest rate pool.\n */\n struct VenusPool {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n }\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IPrime.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { PrimeStorageV1 } from \"../PrimeStorage.sol\";\n\n/**\n * @title IPrime\n * @author Venus\n * @notice Interface for Prime Token\n */\ninterface IPrime {\n struct APRInfo {\n // supply APR of the user in BPS\n uint256 supplyAPR;\n // borrow APR of the user in BPS\n uint256 borrowAPR;\n // total score of the market\n uint256 totalScore;\n // score of the user\n uint256 userScore;\n // capped XVS balance of the user\n uint256 xvsBalanceForScore;\n // capital of the user\n uint256 capital;\n // capped supply of the user\n uint256 cappedSupply;\n // capped borrow of the user\n uint256 cappedBorrow;\n // capped supply of user in USD\n uint256 supplyCapUSD;\n // capped borrow of user in USD\n uint256 borrowCapUSD;\n }\n\n struct Capital {\n // capital of the user\n uint256 capital;\n // capped supply of the user\n uint256 cappedSupply;\n // capped borrow of the user\n uint256 cappedBorrow;\n // capped supply of user in USD\n uint256 supplyCapUSD;\n // capped borrow of user in USD\n uint256 borrowCapUSD;\n }\n\n /**\n * @notice Returns boosted pending interest accrued for a user for all markets\n * @param user the account for which to get the accrued interests\n * @return pendingRewards the number of underlying tokens accrued by the user for all markets\n */\n function getPendingRewards(address user) external returns (PrimeStorageV1.PendingReward[] memory pendingRewards);\n\n /**\n * @notice Update total score of multiple users and market\n * @param users accounts for which we need to update score\n */\n function updateScores(address[] memory users) external;\n\n /**\n * @notice Update value of alpha\n * @param _alphaNumerator numerator of alpha. If alpha is 0.5 then numerator is 1\n * @param _alphaDenominator denominator of alpha. If alpha is 0.5 then denominator is 2\n */\n function updateAlpha(uint128 _alphaNumerator, uint128 _alphaDenominator) external;\n\n /**\n * @notice Update multipliers for a market\n * @param market address of the market vToken\n * @param supplyMultiplier new supply multiplier for the market, scaled by 1e18\n * @param borrowMultiplier new borrow multiplier for the market, scaled by 1e18\n */\n function updateMultipliers(address market, uint256 supplyMultiplier, uint256 borrowMultiplier) external;\n\n /**\n * @notice Add a market to prime program\n * @param comptroller address of the comptroller\n * @param market address of the market vToken\n * @param supplyMultiplier the multiplier for supply cap. It should be converted to 1e18\n * @param borrowMultiplier the multiplier for borrow cap. It should be converted to 1e18\n */\n function addMarket(\n address comptroller,\n address market,\n uint256 supplyMultiplier,\n uint256 borrowMultiplier\n ) external;\n\n /**\n * @notice Set limits for total tokens that can be minted\n * @param _irrevocableLimit total number of irrevocable tokens that can be minted\n * @param _revocableLimit total number of revocable tokens that can be minted\n */\n function setLimit(uint256 _irrevocableLimit, uint256 _revocableLimit) external;\n\n /**\n * @notice Directly issue prime tokens to users\n * @param isIrrevocable are the tokens being issued\n * @param users list of address to issue tokens to\n */\n function issue(bool isIrrevocable, address[] calldata users) external;\n\n /**\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\n * @param user the account address whose balance was updated\n */\n function xvsUpdated(address user) external;\n\n /**\n * @notice accrues interest and updates score for an user for a specific market\n * @param user the account address for which to accrue interest and update score\n * @param market the market for which to accrue interest and update score\n */\n function accrueInterestAndUpdateScore(address user, address market) external;\n\n /**\n * @notice For claiming prime token when staking period is completed\n */\n function claim() external;\n\n /**\n * @notice For burning any prime token\n * @param user the account address for which the prime token will be burned\n */\n function burn(address user) external;\n\n /**\n * @notice To pause or unpause claiming of interest\n */\n function togglePause() external;\n\n /**\n * @notice For user to claim boosted yield\n * @param vToken the market for which claim the accrued interest\n * @return amount the amount of tokens transferred to the user\n */\n function claimInterest(address vToken) external returns (uint256);\n\n /**\n * @notice For user to claim boosted yield\n * @param vToken the market for which claim the accrued interest\n * @param user the user for which to claim the accrued interest\n * @return amount the amount of tokens transferred to the user\n */\n function claimInterest(address vToken, address user) external returns (uint256);\n\n /**\n * @notice Distributes income from market since last distribution\n * @param vToken the market for which to distribute the income\n */\n function accrueInterest(address vToken) external;\n\n /**\n * @notice Returns boosted interest accrued for a user\n * @param vToken the market for which to fetch the accrued interest\n * @param user the account for which to get the accrued interest\n * @return interestAccrued the number of underlying tokens accrued by the user since the last accrual\n */\n function getInterestAccrued(address vToken, address user) external returns (uint256);\n\n /**\n * @notice Retrieves an array of all available markets\n * @return an array of addresses representing all available markets\n */\n function getAllMarkets() external view returns (address[] memory);\n\n /**\n * @notice fetch the numbers of seconds remaining for staking period to complete\n * @param user the account address for which we are checking the remaining time\n * @return timeRemaining the number of seconds the user needs to wait to claim prime token\n */\n function claimTimeRemaining(address user) external view returns (uint256);\n\n /**\n * @notice Returns supply and borrow APR for user for a given market\n * @param market the market for which to fetch the APR\n * @param user the account for which to get the APR\n * @return aprInfo APR information for the user for the given market\n */\n function calculateAPR(address market, address user) external view returns (APRInfo memory aprInfo);\n\n /**\n * @notice Returns supply and borrow APR for estimated supply, borrow and XVS staked\n * @param market the market for which to fetch the APR\n * @param user the account for which to get the APR\n * @param borrow hypothetical borrow amount\n * @param supply hypothetical supply amount\n * @param xvsStaked hypothetical staked XVS amount\n * @return aprInfo APR information for the user for the given market\n */\n function estimateAPR(\n address market,\n address user,\n uint256 borrow,\n uint256 supply,\n uint256 xvsStaked\n ) external view returns (APRInfo memory aprInfo);\n\n /**\n * @notice the total income that's going to be distributed in a year to prime token holders\n * @param vToken the market for which to fetch the total income that's going to distributed in a year\n * @return amount the total income\n */\n function incomeDistributionYearly(address vToken) external view returns (uint256 amount);\n\n /**\n * @notice Returns if user is a prime holder\n * @return isPrimeHolder true if user is a prime holder\n */\n function isUserPrimeHolder(address user) external view returns (bool);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param loopsLimit Number of loops limit\n */\n function setMaxLoopsLimit(uint256 loopsLimit) external;\n\n /**\n * @notice Update staked at timestamp for multiple users\n * @param users accounts for which we need to update staked at timestamp\n * @param timestamps new staked at timestamp for the users\n */\n function setStakedAt(address[] calldata users, uint256[] calldata timestamps) external;\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IPrimeLiquidityProvider.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n/**\n * @title IPrimeLiquidityProvider\n * @author Venus\n * @notice Interface for PrimeLiquidityProvider\n */\ninterface IPrimeLiquidityProvider {\n /**\n * @notice Initialize the distribution of the token\n * @param tokens_ Array of addresses of the tokens to be intialized\n */\n function initializeTokens(address[] calldata tokens_) external;\n\n /**\n * @notice Pause fund transfer of tokens to Prime contract\n */\n function pauseFundsTransfer() external;\n\n /**\n * @notice Resume fund transfer of tokens to Prime contract\n */\n function resumeFundsTransfer() external;\n\n /**\n * @notice Set distribution speed (amount of token distribute per block or second)\n * @param tokens_ Array of addresses of the tokens\n * @param distributionSpeeds_ New distribution speeds for tokens\n */\n function setTokensDistributionSpeed(address[] calldata tokens_, uint256[] calldata distributionSpeeds_) external;\n\n /**\n * @notice Set max distribution speed for token (amount of maximum token distribute per block or second)\n * @param tokens_ Array of addresses of the tokens\n * @param maxDistributionSpeeds_ New distribution speeds for tokens\n */\n function setMaxTokensDistributionSpeed(\n address[] calldata tokens_,\n uint256[] calldata maxDistributionSpeeds_\n ) external;\n\n /**\n * @notice Set the prime token contract address\n * @param prime_ The new address of the prime token contract\n */\n function setPrimeToken(address prime_) external;\n\n /**\n * @notice Claim all the token accrued till last block or second\n * @param token_ The token to release to the Prime contract\n */\n function releaseFunds(address token_) external;\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to user\n * @param token_ The address of the ERC-20 token to sweep\n * @param to_ The address of the recipient\n * @param amount_ The amount of tokens needs to transfer\n */\n function sweepToken(IERC20Upgradeable token_, address to_, uint256 amount_) external;\n\n /**\n * @notice Accrue token by updating the distribution state\n * @param token_ Address of the token\n */\n function accrueTokens(address token_) external;\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param loopsLimit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 loopsLimit) external;\n\n /**\n * @notice Get rewards per block or second for token\n * @param token_ Address of the token\n * @return speed returns the per block or second reward\n */\n function getEffectiveDistributionSpeed(address token_) external view returns (uint256);\n\n /**\n * @notice Get the amount of tokens accrued\n * @param token_ Address of the token\n * @return Amount of tokens that are accrued\n */\n function tokenAmountAccrued(address token_) external view returns (uint256);\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IVToken {\n function borrowBalanceStored(address account) external view returns (uint256);\n\n function exchangeRateStored() external view returns (uint256);\n\n function balanceOf(address account) external view returns (uint256);\n\n function underlying() external view returns (address);\n\n function totalBorrows() external view returns (uint256);\n\n function borrowRatePerBlock() external view returns (uint256);\n\n function reserveFactorMantissa() external view returns (uint256);\n\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IXVSVault.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IXVSVault {\n function getUserInfo(\n address _rewardToken,\n uint256 _pid,\n address _user\n ) external view returns (uint256 amount, uint256 rewardDebt, uint256 pendingWithdrawals);\n\n function xvsAddress() external view returns (address);\n}\n" + }, + "contracts/Tokens/Prime/IPrime.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title IPrime\n * @author Venus\n * @notice Interface for Prime Token\n */\ninterface IPrime {\n /**\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\n * @param user the account address whose balance was updated\n */\n function xvsUpdated(address user) external;\n\n /**\n * @notice accrues interest and updates score for an user for a specific market\n * @param user the account address for which to accrue interest and update score\n * @param market the market for which to accrue interest and update score\n */\n function accrueInterestAndUpdateScore(address user, address market) external;\n\n /**\n * @notice Distributes income from market since last distribution\n * @param vToken the market for which to distribute the income\n */\n function accrueInterest(address vToken) external;\n\n /**\n * @notice Returns if user is a prime holder\n * @param isPrimeHolder returns if the user is a prime holder\n */\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\n}\n" + }, + "contracts/Tokens/Prime/libs/FixedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable var-name-mixedcase\n\npragma solidity 0.8.25;\n\nimport { SafeCastUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol\";\nimport { FixedMath0x } from \"./FixedMath0x.sol\";\n\nusing SafeCastUpgradeable for uint256;\n\nerror InvalidFixedPoint();\n\n/**\n * @title FixedMath\n * @author Venus\n * @notice FixedMath library is used for complex mathematical operations\n */\nlibrary FixedMath {\n error InvalidFraction(uint256 n, uint256 d);\n\n /**\n * @notice Convert some uint256 fraction `n` numerator / `d` denominator to a fixed-point number `f`.\n * @param n numerator\n * @param d denominator\n * @return fixed-point number\n */\n function _toFixed(uint256 n, uint256 d) internal pure returns (int256) {\n if (d.toInt256() < n.toInt256()) revert InvalidFraction(n, d);\n\n return (n.toInt256() * FixedMath0x.FIXED_1) / int256(d.toInt256());\n }\n\n /**\n * @notice Divide some unsigned int `u` by a fixed point number `f`\n * @param u unsigned dividend\n * @param f fixed point divisor, in FIXED_1 units\n * @return unsigned int quotient\n */\n function _uintDiv(uint256 u, int256 f) internal pure returns (uint256) {\n if (f < 0) revert InvalidFixedPoint();\n // multiply `u` by FIXED_1 to cancel out the built-in FIXED_1 in f\n return uint256((u.toInt256() * FixedMath0x.FIXED_1) / f);\n }\n\n /**\n * @notice Multiply some unsigned int `u` by a fixed point number `f`\n * @param u unsigned multiplicand\n * @param f fixed point multiplier, in FIXED_1 units\n * @return unsigned int product\n */\n function _uintMul(uint256 u, int256 f) internal pure returns (uint256) {\n if (f < 0) revert InvalidFixedPoint();\n // divide the product by FIXED_1 to cancel out the built-in FIXED_1 in f\n return uint256((u.toInt256() * f) / FixedMath0x.FIXED_1);\n }\n\n /// @notice see FixedMath0x\n function _ln(int256 x) internal pure returns (int256) {\n return FixedMath0x._ln(x);\n }\n\n /// @notice see FixedMath0x\n function _exp(int256 x) internal pure returns (int256) {\n return FixedMath0x._exp(x);\n }\n}\n" + }, + "contracts/Tokens/Prime/libs/FixedMath0x.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable max-line-length\n\npragma solidity 0.8.25;\n\n// Below is code from 0x's LibFixedMath.sol. Changes:\n// - addition of 0.8-style errors\n// - removal of unused functions\n// - added comments for clarity\n// https://github.com/0xProject/exchange-v3/blob/aae46bef841bfd1cc31028f41793db4fe7197084/contracts/staking/contracts/src/libs/LibFixedMath.sol\n\n/*\n\n Copyright 2017 Bprotocol Foundation, 2019 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n/// Thrown when the natural log function is given too large of an argument\nerror LnTooLarge(int256 x);\n/// Thrown when the natural log would have returned a number outside of ℝ\nerror LnNonRealResult(int256 x);\n/// Thrown when exp is given too large of an argument\nerror ExpTooLarge(int256 x);\n/// Thrown when an unsigned value is too large to be converted to a signed value\nerror UnsignedValueTooLarge(uint256 x);\n\n/**\n * @title FixedMath0x\n * @notice Signed, fixed-point, 127-bit precision math library\n */\nlibrary FixedMath0x {\n // Base for the fixed point numbers (this is our 1)\n int256 internal constant FIXED_1 = int256(0x0000000000000000000000000000000080000000000000000000000000000000);\n // Maximum ln argument (1)\n int256 private constant LN_MAX_VAL = FIXED_1;\n // Minimum ln argument. Notice this is related to EXP_MIN_VAL (e ^ -63.875)\n int256 private constant LN_MIN_VAL = int256(0x0000000000000000000000000000000000000000000000000000000733048c5a);\n // Maximum exp argument (0)\n int256 private constant EXP_MAX_VAL = 0;\n // Minimum exp argument. Notice this is related to LN_MIN_VAL (-63.875)\n int256 private constant EXP_MIN_VAL = -int256(0x0000000000000000000000000000001ff0000000000000000000000000000000);\n\n /// @dev Get the natural logarithm of a fixed-point number 0 < `x` <= LN_MAX_VAL\n function _ln(int256 x) internal pure returns (int256 r) {\n if (x > LN_MAX_VAL) {\n revert LnTooLarge(x);\n }\n if (x <= 0) {\n revert LnNonRealResult(x);\n }\n if (x == FIXED_1) {\n return 0;\n }\n if (x <= LN_MIN_VAL) {\n return EXP_MIN_VAL;\n }\n\n int256 y;\n int256 z;\n int256 w;\n\n // Rewrite the input as a quotient of negative natural exponents and a single residual q, such that 1 < q < 2\n // For example: log(0.3) = log(e^-1 * e^-0.25 * 1.0471028872385522)\n // = 1 - 0.25 - log(1 + 0.0471028872385522)\n // e ^ -32\n if (x <= int256(0x00000000000000000000000000000000000000000001c8464f76164760000000)) {\n r -= int256(0x0000000000000000000000000000001000000000000000000000000000000000); // - 32\n x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000000001c8464f76164760000000); // / e ^ -32\n }\n // e ^ -16\n if (x <= int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000)) {\n r -= int256(0x0000000000000000000000000000000800000000000000000000000000000000); // - 16\n x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000); // / e ^ -16\n }\n // e ^ -8\n if (x <= int256(0x00000000000000000000000000000000000afe10820813d78000000000000000)) {\n r -= int256(0x0000000000000000000000000000000400000000000000000000000000000000); // - 8\n x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000afe10820813d78000000000000000); // / e ^ -8\n }\n // e ^ -4\n if (x <= int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000)) {\n r -= int256(0x0000000000000000000000000000000200000000000000000000000000000000); // - 4\n x = (x * FIXED_1) / int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000); // / e ^ -4\n }\n // e ^ -2\n if (x <= int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000)) {\n r -= int256(0x0000000000000000000000000000000100000000000000000000000000000000); // - 2\n x = (x * FIXED_1) / int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000); // / e ^ -2\n }\n // e ^ -1\n if (x <= int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000)) {\n r -= int256(0x0000000000000000000000000000000080000000000000000000000000000000); // - 1\n x = (x * FIXED_1) / int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000); // / e ^ -1\n }\n // e ^ -0.5\n if (x <= int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000)) {\n r -= int256(0x0000000000000000000000000000000040000000000000000000000000000000); // - 0.5\n x = (x * FIXED_1) / int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000); // / e ^ -0.5\n }\n // e ^ -0.25\n if (x <= int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000)) {\n r -= int256(0x0000000000000000000000000000000020000000000000000000000000000000); // - 0.25\n x = (x * FIXED_1) / int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000); // / e ^ -0.25\n }\n // e ^ -0.125\n if (x <= int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d)) {\n r -= int256(0x0000000000000000000000000000000010000000000000000000000000000000); // - 0.125\n x = (x * FIXED_1) / int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d); // / e ^ -0.125\n }\n // `x` is now our residual in the range of 1 <= x <= 2 (or close enough).\n\n // Add the taylor series for log(1 + z), where z = x - 1\n z = y = x - FIXED_1;\n w = (y * y) / FIXED_1;\n r += (z * (0x100000000000000000000000000000000 - y)) / 0x100000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^01 / 01 - y^02 / 02\n r += (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / 0x200000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^03 / 03 - y^04 / 04\n r += (z * (0x099999999999999999999999999999999 - y)) / 0x300000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^05 / 05 - y^06 / 06\n r += (z * (0x092492492492492492492492492492492 - y)) / 0x400000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^07 / 07 - y^08 / 08\n r += (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / 0x500000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^09 / 09 - y^10 / 10\n r += (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / 0x600000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^11 / 11 - y^12 / 12\n r += (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / 0x700000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^13 / 13 - y^14 / 14\n r += (z * (0x088888888888888888888888888888888 - y)) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16\n }\n\n /// @dev Compute the natural exponent for a fixed-point number EXP_MIN_VAL <= `x` <= 1\n function _exp(int256 x) internal pure returns (int256 r) {\n if (x < EXP_MIN_VAL) {\n // Saturate to zero below EXP_MIN_VAL.\n return 0;\n }\n if (x == 0) {\n return FIXED_1;\n }\n if (x > EXP_MAX_VAL) {\n revert ExpTooLarge(x);\n }\n\n // Rewrite the input as a product of natural exponents and a\n // single residual q, where q is a number of small magnitude.\n // For example: e^-34.419 = e^(-32 - 2 - 0.25 - 0.125 - 0.044)\n // = e^-32 * e^-2 * e^-0.25 * e^-0.125 * e^-0.044\n // -> q = -0.044\n\n // Multiply with the taylor series for e^q\n int256 y;\n int256 z;\n // q = x % 0.125 (the residual)\n z = y = x % 0x0000000000000000000000000000000010000000000000000000000000000000;\n z = (z * y) / FIXED_1;\n r += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!)\n z = (z * y) / FIXED_1;\n r += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!)\n z = (z * y) / FIXED_1;\n r += z * 0x0168244fdac78000; // add y^04 * (20! / 04!)\n z = (z * y) / FIXED_1;\n r += z * 0x004807432bc18000; // add y^05 * (20! / 05!)\n z = (z * y) / FIXED_1;\n r += z * 0x000c0135dca04000; // add y^06 * (20! / 06!)\n z = (z * y) / FIXED_1;\n r += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!)\n z = (z * y) / FIXED_1;\n r += z * 0x000036e0f639b800; // add y^08 * (20! / 08!)\n z = (z * y) / FIXED_1;\n r += z * 0x00000618fee9f800; // add y^09 * (20! / 09!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000e30dce400; // add y^11 * (20! / 11!)\n z = (z * y) / FIXED_1;\n r += z * 0x000000012ebd1300; // add y^12 * (20! / 12!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000017499f00; // add y^13 * (20! / 13!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000001a9d480; // add y^14 * (20! / 14!)\n z = (z * y) / FIXED_1;\n r += z * 0x00000000001c6380; // add y^15 * (20! / 15!)\n z = (z * y) / FIXED_1;\n r += z * 0x000000000001c638; // add y^16 * (20! / 16!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000000001ab8; // add y^17 * (20! / 17!)\n z = (z * y) / FIXED_1;\n r += z * 0x000000000000017c; // add y^18 * (20! / 18!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000000000014; // add y^19 * (20! / 19!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000000000001; // add y^20 * (20! / 20!)\n r = r / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0!\n\n // Multiply with the non-residual terms.\n x = -x;\n // e ^ -32\n if ((x & int256(0x0000000000000000000000000000001000000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x00000000000000000000000000000000000000f1aaddd7742e56d32fb9f99744)) /\n int256(0x0000000000000000000000000043cbaf42a000812488fc5c220ad7b97bf6e99e); // * e ^ -32\n }\n // e ^ -16\n if ((x & int256(0x0000000000000000000000000000000800000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x00000000000000000000000000000000000afe10820813d65dfe6a33c07f738f)) /\n int256(0x000000000000000000000000000005d27a9f51c31b7c2f8038212a0574779991); // * e ^ -16\n }\n // e ^ -8\n if ((x & int256(0x0000000000000000000000000000000400000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x0000000000000000000000000000000002582ab704279e8efd15e0265855c47a)) /\n int256(0x0000000000000000000000000000001b4c902e273a58678d6d3bfdb93db96d02); // * e ^ -8\n }\n // e ^ -4\n if ((x & int256(0x0000000000000000000000000000000200000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x000000000000000000000000000000001152aaa3bf81cb9fdb76eae12d029571)) /\n int256(0x00000000000000000000000000000003b1cc971a9bb5b9867477440d6d157750); // * e ^ -4\n }\n // e ^ -2\n if ((x & int256(0x0000000000000000000000000000000100000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x000000000000000000000000000000002f16ac6c59de6f8d5d6f63c1482a7c86)) /\n int256(0x000000000000000000000000000000015bf0a8b1457695355fb8ac404e7a79e3); // * e ^ -2\n }\n // e ^ -1\n if ((x & int256(0x0000000000000000000000000000000080000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x000000000000000000000000000000004da2cbf1be5827f9eb3ad1aa9866ebb3)) /\n int256(0x00000000000000000000000000000000d3094c70f034de4b96ff7d5b6f99fcd8); // * e ^ -1\n }\n // e ^ -0.5\n if ((x & int256(0x0000000000000000000000000000000040000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x0000000000000000000000000000000063afbe7ab2082ba1a0ae5e4eb1b479dc)) /\n int256(0x00000000000000000000000000000000a45af1e1f40c333b3de1db4dd55f29a7); // * e ^ -0.5\n }\n // e ^ -0.25\n if ((x & int256(0x0000000000000000000000000000000020000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d)) /\n int256(0x00000000000000000000000000000000910b022db7ae67ce76b441c27035c6a1); // * e ^ -0.25\n }\n // e ^ -0.125\n if ((x & int256(0x0000000000000000000000000000000010000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x00000000000000000000000000000000783eafef1c0a8f3978c7f81824d62ebf)) /\n int256(0x0000000000000000000000000000000088415abbe9a76bead8d00cf112e4d4a8); // * e ^ -0.125\n }\n }\n}\n" + }, + "contracts/Tokens/Prime/libs/Scores.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { SafeCastUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol\";\nimport { FixedMath } from \"./FixedMath.sol\";\n\nusing SafeCastUpgradeable for uint256;\n\n/**\n * @title Scores\n * @author Venus\n * @notice Scores library is used to calculate score of users\n */\nlibrary Scores {\n /**\n * @notice Calculate a membership score given some amount of `xvs` and `capital`, along\n * with some 𝝰 = `alphaNumerator` / `alphaDenominator`.\n * @param xvs amount of xvs (xvs, 1e18 decimal places)\n * @param capital amount of capital (1e18 decimal places)\n * @param alphaNumerator alpha param numerator\n * @param alphaDenominator alpha param denominator\n * @return membership score with 1e18 decimal places\n *\n * @dev 𝝰 must be in the range [0, 1]\n */\n function _calculateScore(\n uint256 xvs,\n uint256 capital,\n uint256 alphaNumerator,\n uint256 alphaDenominator\n ) internal pure returns (uint256) {\n // Score function is:\n // xvs^𝝰 * capital^(1-𝝰)\n // = capital * capital^(-𝝰) * xvs^𝝰\n // = capital * (xvs / capital)^𝝰\n // = capital * (e ^ (ln(xvs / capital))) ^ 𝝰\n // = capital * e ^ (𝝰 * ln(xvs / capital)) (1)\n // or\n // = capital / ( 1 / e ^ (𝝰 * ln(xvs / capital)))\n // = capital / (e ^ (𝝰 * ln(xvs / capital)) ^ -1)\n // = capital / e ^ (𝝰 * -1 * ln(xvs / capital))\n // = capital / e ^ (𝝰 * ln(capital / xvs)) (2)\n //\n // To avoid overflows, use (1) when xvs < capital and\n // use (2) when capital < xvs\n\n // If any side is 0, exit early\n if (xvs == 0 || capital == 0) return 0;\n\n // If both sides are equal, we have:\n // xvs^𝝰 * capital^(1-𝝰)\n // = xvs^𝝰 * xvs^(1-𝝰)\n // = xvs^(𝝰 + 1 - 𝝰) = xvs\n if (xvs == capital) return xvs;\n\n bool lessxvsThanCapital = xvs < capital;\n\n // (xvs / capital) or (capital / xvs), always in range (0, 1)\n int256 ratio = lessxvsThanCapital ? FixedMath._toFixed(xvs, capital) : FixedMath._toFixed(capital, xvs);\n\n // e ^ ( ln(ratio) * 𝝰 )\n int256 exponentiation = FixedMath._exp(\n (FixedMath._ln(ratio) * alphaNumerator.toInt256()) / alphaDenominator.toInt256()\n );\n\n if (lessxvsThanCapital) {\n // capital * e ^ (𝝰 * ln(xvs / capital))\n return FixedMath._uintMul(capital, exponentiation);\n }\n\n // capital / e ^ (𝝰 * ln(capital / xvs))\n return FixedMath._uintDiv(capital, exponentiation);\n }\n}\n" + }, + "contracts/Tokens/Prime/Prime.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { IERC20MetadataUpgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\nimport { PrimeStorageV1 } from \"./PrimeStorage.sol\";\nimport { Scores } from \"./libs/Scores.sol\";\n\nimport { IPrimeLiquidityProvider } from \"./Interfaces/IPrimeLiquidityProvider.sol\";\nimport { IPrime } from \"./Interfaces/IPrime.sol\";\nimport { IXVSVault } from \"./Interfaces/IXVSVault.sol\";\nimport { IVToken } from \"./Interfaces/IVToken.sol\";\nimport { InterfaceComptroller } from \"./Interfaces/InterfaceComptroller.sol\";\nimport { PoolRegistryInterface } from \"./Interfaces/IPoolRegistry.sol\";\n\n/**\n * @title Prime\n * @author Venus\n * @notice Prime Token is used to provide extra rewards to the users who have staked a minimum of `MINIMUM_STAKED_XVS` XVS in the XVSVault for `STAKING_PERIOD` days\n * @custom:security-contact https://github.com/VenusProtocol/venus-protocol\n */\ncontract Prime is IPrime, AccessControlledV8, PausableUpgradeable, MaxLoopsLimitHelper, PrimeStorageV1, TimeManagerV8 {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice address of wrapped native token contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WRAPPED_NATIVE_TOKEN;\n\n /// @notice address of native market contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_MARKET;\n\n /// @notice minimum amount of XVS user needs to stake to become a prime member\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable MINIMUM_STAKED_XVS;\n\n /// @notice maximum XVS taken in account when calculating user score\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable MAXIMUM_XVS_CAP;\n\n /// @notice number of days user need to stake to claim prime token\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable STAKING_PERIOD;\n\n /// @notice Emitted when prime token is minted\n event Mint(address indexed user, bool isIrrevocable);\n\n /// @notice Emitted when prime token is burned\n event Burn(address indexed user);\n\n /// @notice Emitted when a market is added to prime program\n event MarketAdded(\n address indexed comptroller,\n address indexed market,\n uint256 supplyMultiplier,\n uint256 borrowMultiplier\n );\n\n /// @notice Emitted when mint limits are updated\n event MintLimitsUpdated(\n uint256 indexed oldIrrevocableLimit,\n uint256 indexed oldRevocableLimit,\n uint256 indexed newIrrevocableLimit,\n uint256 newRevocableLimit\n );\n\n /// @notice Emitted when user score is updated\n event UserScoreUpdated(address indexed user);\n\n /// @notice Emitted when alpha is updated\n event AlphaUpdated(\n uint128 indexed oldNumerator,\n uint128 indexed oldDenominator,\n uint128 indexed newNumerator,\n uint128 newDenominator\n );\n\n /// @notice Emitted when multiplier is updated\n event MultiplierUpdated(\n address indexed market,\n uint256 indexed oldSupplyMultiplier,\n uint256 indexed oldBorrowMultiplier,\n uint256 newSupplyMultiplier,\n uint256 newBorrowMultiplier\n );\n\n /// @notice Emitted when interest is claimed\n event InterestClaimed(address indexed user, address indexed market, uint256 amount);\n\n /// @notice Emitted when revocable token is upgraded to irrevocable token\n event TokenUpgraded(address indexed user);\n\n /// @notice Emitted when stakedAt is updated\n event StakedAtUpdated(address indexed user, uint256 timestamp);\n\n /// @notice Error thrown when market is not supported\n error MarketNotSupported();\n\n /// @notice Error thrown when mint limit is reached\n error InvalidLimit();\n\n /// @notice Error thrown when user is not eligible to claim prime token\n error IneligibleToClaim();\n\n /// @notice Error thrown when user needs to wait more time to claim prime token\n error WaitMoreTime();\n\n /// @notice Error thrown when user has no prime token\n error UserHasNoPrimeToken();\n\n /// @notice Error thrown when no score updates are required\n error NoScoreUpdatesRequired();\n\n /// @notice Error thrown when market already exists\n error MarketAlreadyExists();\n\n /// @notice Error thrown when asset already exists\n error AssetAlreadyExists();\n\n /// @notice Error thrown when invalid address is passed\n error InvalidAddress();\n\n /// @notice Error thrown when invalid alpha arguments are passed\n error InvalidAlphaArguments();\n\n /// @notice Error thrown when invalid vToken is passed\n error InvalidVToken();\n\n /// @notice Error thrown when invalid length is passed\n error InvalidLength();\n\n /// @notice Error thrown when timestamp is invalid\n error InvalidTimestamp();\n\n /// @notice Error thrown when invalid comptroller is passed\n error InvalidComptroller();\n\n /**\n * @notice Prime constructor\n * @param _wrappedNativeToken Address of wrapped native token\n * @param _nativeMarket Address of native market\n * @param _blocksPerYear total blocks per year\n * @param _stakingPeriod total number of seconds for which user needs to stake to claim prime token\n * @param _minimumStakedXVS minimum amount of XVS user needs to stake to become a prime member (scaled by 1e18)\n * @param _maximumXVSCap maximum XVS taken in account when calculating user score (scaled by 1e18)\n * @param _timeBased A boolean indicating whether the contract is based on time or block.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeToken,\n address _nativeMarket,\n uint256 _blocksPerYear,\n uint256 _stakingPeriod,\n uint256 _minimumStakedXVS,\n uint256 _maximumXVSCap,\n bool _timeBased\n ) TimeManagerV8(_timeBased, _blocksPerYear) {\n WRAPPED_NATIVE_TOKEN = _wrappedNativeToken;\n NATIVE_MARKET = _nativeMarket;\n STAKING_PERIOD = _stakingPeriod;\n MINIMUM_STAKED_XVS = _minimumStakedXVS;\n MAXIMUM_XVS_CAP = _maximumXVSCap;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Prime initializer\n * @param xvsVault_ Address of XVSVault\n * @param xvsVaultRewardToken_ Address of XVSVault reward token\n * @param xvsVaultPoolId_ Pool id of XVSVault\n * @param alphaNumerator_ numerator of alpha. If alpha is 0.5 then numerator is 1.\n alphaDenominator_ must be greater than alphaNumerator_, alphaDenominator_ cannot be zero and alphaNumerator_ cannot be zero\n * @param alphaDenominator_ denominator of alpha. If alpha is 0.5 then denominator is 2.\n alpha is alphaNumerator_/alphaDenominator_. So, 0 < alpha < 1\n * @param accessControlManager_ Address of AccessControlManager\n * @param primeLiquidityProvider_ Address of PrimeLiquidityProvider\n * @param comptroller_ Address of core pool comptroller\n * @param oracle_ Address of Oracle\n * @param loopsLimit_ Maximum number of loops allowed in a single transaction\n * @custom:error Throw InvalidAddress if any of the address is invalid\n */\n function initialize(\n address xvsVault_,\n address xvsVaultRewardToken_,\n uint256 xvsVaultPoolId_,\n uint128 alphaNumerator_,\n uint128 alphaDenominator_,\n address accessControlManager_,\n address primeLiquidityProvider_,\n address comptroller_,\n address oracle_,\n uint256 loopsLimit_\n ) external initializer {\n if (xvsVault_ == address(0)) revert InvalidAddress();\n if (xvsVaultRewardToken_ == address(0)) revert InvalidAddress();\n if (oracle_ == address(0)) revert InvalidAddress();\n if (primeLiquidityProvider_ == address(0)) revert InvalidAddress();\n\n _checkAlphaArguments(alphaNumerator_, alphaDenominator_);\n\n alphaNumerator = alphaNumerator_;\n alphaDenominator = alphaDenominator_;\n xvsVaultRewardToken = xvsVaultRewardToken_;\n xvsVaultPoolId = xvsVaultPoolId_;\n xvsVault = xvsVault_;\n nextScoreUpdateRoundId = 0;\n primeLiquidityProvider = primeLiquidityProvider_;\n corePoolComptroller = comptroller_;\n oracle = ResilientOracleInterface(oracle_);\n\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n _setMaxLoopsLimit(loopsLimit_);\n\n _pause();\n }\n\n /**\n * @notice Prime initializer V2 for initializing pool registry\n * @param poolRegistry_ Address of IL pool registry\n */\n function initializeV2(address poolRegistry_) external reinitializer(2) {\n poolRegistry = poolRegistry_;\n }\n\n /**\n * @notice Returns boosted pending interest accrued for a user for all markets\n * @param user the account for which to get the accrued interests\n * @return pendingRewards the number of underlying tokens accrued by the user for all markets\n */\n function getPendingRewards(address user) external returns (PendingReward[] memory pendingRewards) {\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n pendingRewards = new PendingReward[](marketsLength);\n for (uint256 i; i < marketsLength; ) {\n address market = allMarkets[i];\n uint256 interestAccrued = getInterestAccrued(market, user);\n uint256 accrued = interests[market][user].accrued;\n\n pendingRewards[i] = PendingReward({\n vToken: market,\n rewardToken: _getUnderlying(market),\n amount: interestAccrued + accrued\n });\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Update total score of multiple users and market\n * @param users accounts for which we need to update score\n * @custom:error Throw NoScoreUpdatesRequired if no score updates are required\n * @custom:error Throw UserHasNoPrimeToken if user has no prime token\n * @custom:event Emits UserScoreUpdated event\n */\n function updateScores(address[] calldata users) external {\n if (pendingScoreUpdates == 0) revert NoScoreUpdatesRequired();\n if (nextScoreUpdateRoundId == 0) revert NoScoreUpdatesRequired();\n\n for (uint256 i; i < users.length; ) {\n address user = users[i];\n\n if (!tokens[user].exists) revert UserHasNoPrimeToken();\n if (isScoreUpdated[nextScoreUpdateRoundId][user]) {\n unchecked {\n ++i;\n }\n continue;\n }\n\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n for (uint256 j; j < marketsLength; ) {\n address market = allMarkets[j];\n _executeBoost(user, market);\n _updateScore(user, market);\n\n unchecked {\n ++j;\n }\n }\n\n --pendingScoreUpdates;\n isScoreUpdated[nextScoreUpdateRoundId][user] = true;\n\n unchecked {\n ++i;\n }\n\n emit UserScoreUpdated(user);\n }\n }\n\n /**\n * @notice Update value of alpha\n * @param _alphaNumerator numerator of alpha. If alpha is 0.5 then numerator is 1\n * @param _alphaDenominator denominator of alpha. If alpha is 0.5 then denominator is 2\n * @custom:event Emits AlphaUpdated event\n * @custom:access Controlled by ACM\n */\n function updateAlpha(uint128 _alphaNumerator, uint128 _alphaDenominator) external {\n _checkAccessAllowed(\"updateAlpha(uint128,uint128)\");\n _checkAlphaArguments(_alphaNumerator, _alphaDenominator);\n\n emit AlphaUpdated(alphaNumerator, alphaDenominator, _alphaNumerator, _alphaDenominator);\n\n alphaNumerator = _alphaNumerator;\n alphaDenominator = _alphaDenominator;\n\n uint256 marketslength = _allMarkets.length;\n\n for (uint256 i; i < marketslength; ) {\n accrueInterest(_allMarkets[i]);\n\n unchecked {\n ++i;\n }\n }\n\n _startScoreUpdateRound();\n }\n\n /**\n * @notice Update multipliers for a market\n * @param market address of the market vToken\n * @param supplyMultiplier new supply multiplier for the market, scaled by 1e18\n * @param borrowMultiplier new borrow multiplier for the market, scaled by 1e18\n * @custom:error Throw MarketNotSupported if market is not supported\n * @custom:event Emits MultiplierUpdated event\n * @custom:access Controlled by ACM\n */\n function updateMultipliers(address market, uint256 supplyMultiplier, uint256 borrowMultiplier) external {\n _checkAccessAllowed(\"updateMultipliers(address,uint256,uint256)\");\n\n Market storage _market = markets[market];\n if (!_market.exists) revert MarketNotSupported();\n\n accrueInterest(market);\n\n emit MultiplierUpdated(\n market,\n _market.supplyMultiplier,\n _market.borrowMultiplier,\n supplyMultiplier,\n borrowMultiplier\n );\n _market.supplyMultiplier = supplyMultiplier;\n _market.borrowMultiplier = borrowMultiplier;\n\n _startScoreUpdateRound();\n }\n\n /**\n * @notice Update staked at timestamp for multiple users\n * @param users accounts for which we need to update staked at timestamp\n * @param timestamps new staked at timestamp for the users\n * @custom:error Throw InvalidLength if users and timestamps length are not equal\n * @custom:event Emits StakedAtUpdated event for each user\n * @custom:access Controlled by ACM\n */\n function setStakedAt(address[] calldata users, uint256[] calldata timestamps) external {\n _checkAccessAllowed(\"setStakedAt(address[],uint256[])\");\n if (users.length != timestamps.length) revert InvalidLength();\n\n for (uint256 i; i < users.length; ) {\n if (timestamps[i] > block.timestamp) revert InvalidTimestamp();\n\n stakedAt[users[i]] = timestamps[i];\n emit StakedAtUpdated(users[i], timestamps[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Add a market to prime program\n * @param comptroller address of the comptroller\n * @param market address of the market vToken\n * @param supplyMultiplier the multiplier for supply cap. It should be converted to 1e18\n * @param borrowMultiplier the multiplier for borrow cap. It should be converted to 1e18\n * @custom:error Throw MarketAlreadyExists if market already exists\n * @custom:error Throw InvalidVToken if market is not valid\n * @custom:event Emits MarketAdded event\n * @custom:access Controlled by ACM\n */\n function addMarket(\n address comptroller,\n address market,\n uint256 supplyMultiplier,\n uint256 borrowMultiplier\n ) external {\n _checkAccessAllowed(\"addMarket(address,address,uint256,uint256)\");\n\n if (comptroller == address(0)) revert InvalidComptroller();\n\n if (\n comptroller != corePoolComptroller &&\n PoolRegistryInterface(poolRegistry).getPoolByComptroller(comptroller).comptroller != comptroller\n ) revert InvalidComptroller();\n\n Market storage _market = markets[market];\n if (_market.exists) revert MarketAlreadyExists();\n\n bool isMarketExist = InterfaceComptroller(comptroller).markets(market);\n if (!isMarketExist) revert InvalidVToken();\n\n delete _market.rewardIndex;\n _market.supplyMultiplier = supplyMultiplier;\n _market.borrowMultiplier = borrowMultiplier;\n delete _market.sumOfMembersScore;\n _market.exists = true;\n\n address underlying = _getUnderlying(market);\n\n if (vTokenForAsset[underlying] != address(0)) revert AssetAlreadyExists();\n vTokenForAsset[underlying] = market;\n\n _allMarkets.push(market);\n _startScoreUpdateRound();\n\n _ensureMaxLoops(_allMarkets.length);\n\n emit MarketAdded(comptroller, market, supplyMultiplier, borrowMultiplier);\n }\n\n /**\n * @notice Set limits for total tokens that can be minted\n * @param _irrevocableLimit total number of irrevocable tokens that can be minted\n * @param _revocableLimit total number of revocable tokens that can be minted\n * @custom:error Throw InvalidLimit if any of the limit is less than total tokens minted\n * @custom:event Emits MintLimitsUpdated event\n * @custom:access Controlled by ACM\n */\n function setLimit(uint256 _irrevocableLimit, uint256 _revocableLimit) external {\n _checkAccessAllowed(\"setLimit(uint256,uint256)\");\n if (_irrevocableLimit < totalIrrevocable || _revocableLimit < totalRevocable) revert InvalidLimit();\n\n emit MintLimitsUpdated(irrevocableLimit, revocableLimit, _irrevocableLimit, _revocableLimit);\n\n revocableLimit = _revocableLimit;\n irrevocableLimit = _irrevocableLimit;\n }\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param loopsLimit Number of loops limit\n * @custom:event Emits MaxLoopsLimitUpdated event on success\n * @custom:access Controlled by ACM\n */\n function setMaxLoopsLimit(uint256 loopsLimit) external {\n _checkAccessAllowed(\"setMaxLoopsLimit(uint256)\");\n _setMaxLoopsLimit(loopsLimit);\n }\n\n /**\n * @notice Directly issue prime tokens to users\n * @param isIrrevocable are the tokens being issued\n * @param users list of address to issue tokens to\n * @custom:access Controlled by ACM\n */\n function issue(bool isIrrevocable, address[] calldata users) external {\n _checkAccessAllowed(\"issue(bool,address[])\");\n\n if (isIrrevocable) {\n for (uint256 i; i < users.length; ) {\n Token storage userToken = tokens[users[i]];\n if (userToken.exists && !userToken.isIrrevocable) {\n _upgrade(users[i]);\n } else {\n _mint(true, users[i]);\n _initializeMarkets(users[i]);\n }\n\n unchecked {\n ++i;\n }\n }\n } else {\n for (uint256 i; i < users.length; ) {\n _mint(false, users[i]);\n _initializeMarkets(users[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n }\n\n /**\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\n * @param user the account address whose balance was updated\n */\n function xvsUpdated(address user) external {\n uint256 totalStaked = _xvsBalanceOfUser(user);\n bool isAccountEligible = _isEligible(totalStaked);\n\n uint256 userStakedAt = stakedAt[user];\n Token memory token = tokens[user];\n\n if (token.exists && !isAccountEligible) {\n delete stakedAt[user];\n emit StakedAtUpdated(user, 0);\n\n if (token.isIrrevocable) {\n _accrueInterestAndUpdateScore(user);\n } else {\n _burn(user);\n }\n } else if (!isAccountEligible && !token.exists && userStakedAt != 0) {\n delete stakedAt[user];\n emit StakedAtUpdated(user, 0);\n } else if (userStakedAt == 0 && isAccountEligible && !token.exists) {\n stakedAt[user] = block.timestamp;\n emit StakedAtUpdated(user, block.timestamp);\n } else if (token.exists && isAccountEligible) {\n _accrueInterestAndUpdateScore(user);\n\n if (stakedAt[user] == 0) {\n stakedAt[user] = block.timestamp;\n emit StakedAtUpdated(user, block.timestamp);\n }\n }\n }\n\n /**\n * @notice accrues interes and updates score for an user for a specific market\n * @param user the account address for which to accrue interest and update score\n * @param market the market for which to accrue interest and update score\n */\n function accrueInterestAndUpdateScore(address user, address market) external {\n _executeBoost(user, market);\n _updateScore(user, market);\n }\n\n /**\n * @notice For claiming prime token when staking period is completed\n */\n function claim() external {\n uint256 userStakedAt = stakedAt[msg.sender];\n if (userStakedAt == 0) revert IneligibleToClaim();\n if (block.timestamp - userStakedAt < STAKING_PERIOD) revert WaitMoreTime();\n\n _mint(false, msg.sender);\n _initializeMarkets(msg.sender);\n }\n\n /**\n * @notice For burning any prime token\n * @param user the account address for which the prime token will be burned\n * @custom:access Controlled by ACM\n */\n function burn(address user) external {\n _checkAccessAllowed(\"burn(address)\");\n _burn(user);\n }\n\n /**\n * @notice To pause or unpause claiming of interest\n * @custom:access Controlled by ACM\n */\n function togglePause() external {\n _checkAccessAllowed(\"togglePause()\");\n if (paused()) {\n _unpause();\n } else {\n _pause();\n }\n }\n\n /**\n * @notice For user to claim boosted yield\n * @param vToken the market for which claim the accrued interest\n * @return amount the amount of tokens transferred to the msg.sender\n */\n function claimInterest(address vToken) external whenNotPaused returns (uint256) {\n return _claimInterest(vToken, msg.sender);\n }\n\n /**\n * @notice For user to claim boosted yield\n * @param vToken the market for which claim the accrued interest\n * @param user the user for which to claim the accrued interest\n * @return amount the amount of tokens transferred to the user\n */\n function claimInterest(address vToken, address user) external whenNotPaused returns (uint256) {\n return _claimInterest(vToken, user);\n }\n\n /**\n * @notice Retrieves an array of all available markets\n * @return an array of addresses representing all available markets\n */\n function getAllMarkets() external view returns (address[] memory) {\n return _allMarkets;\n }\n\n /**\n * @notice Retrieves the core pool comptroller address\n * @return the core pool comptroller address\n */\n function comptroller() external view returns (address) {\n return corePoolComptroller;\n }\n\n /**\n * @notice fetch the numbers of seconds remaining for staking period to complete\n * @param user the account address for which we are checking the remaining time\n * @return timeRemaining the number of seconds the user needs to wait to claim prime token\n */\n function claimTimeRemaining(address user) external view returns (uint256) {\n uint256 userStakedAt = stakedAt[user];\n if (userStakedAt == 0) return STAKING_PERIOD;\n\n uint256 totalTimeStaked;\n unchecked {\n totalTimeStaked = block.timestamp - userStakedAt;\n }\n\n if (totalTimeStaked < STAKING_PERIOD) {\n unchecked {\n return STAKING_PERIOD - totalTimeStaked;\n }\n }\n return 0;\n }\n\n /**\n * @notice Returns if user is a prime holder\n * @return isPrimeHolder true if user is a prime holder\n */\n function isUserPrimeHolder(address user) external view returns (bool) {\n return tokens[user].exists;\n }\n\n /**\n * @notice Returns supply and borrow APR for user for a given market\n * @param market the market for which to fetch the APR\n * @param user the account for which to get the APR\n * @return aprInfo APR information for the user for the given market\n */\n function calculateAPR(address market, address user) external view returns (APRInfo memory aprInfo) {\n IVToken vToken = IVToken(market);\n uint256 borrow = vToken.borrowBalanceStored(user);\n uint256 exchangeRate = vToken.exchangeRateStored();\n uint256 balanceOfAccount = vToken.balanceOf(user);\n uint256 supply = (exchangeRate * balanceOfAccount) / EXP_SCALE;\n\n aprInfo.userScore = interests[market][user].score;\n aprInfo.totalScore = markets[market].sumOfMembersScore;\n\n aprInfo.xvsBalanceForScore = _xvsBalanceForScore(_xvsBalanceOfUser(user));\n Capital memory capital = _capitalForScore(aprInfo.xvsBalanceForScore, borrow, supply, address(vToken));\n\n aprInfo.capital = capital.capital;\n aprInfo.cappedSupply = capital.cappedSupply;\n aprInfo.cappedBorrow = capital.cappedBorrow;\n aprInfo.supplyCapUSD = capital.supplyCapUSD;\n aprInfo.borrowCapUSD = capital.borrowCapUSD;\n\n (aprInfo.supplyAPR, aprInfo.borrowAPR) = _calculateUserAPR(\n market,\n supply,\n borrow,\n aprInfo.cappedSupply,\n aprInfo.cappedBorrow,\n aprInfo.userScore,\n aprInfo.totalScore\n );\n }\n\n /**\n * @notice Returns supply and borrow APR for estimated supply, borrow and XVS staked\n * @param market the market for which to fetch the APR\n * @param user the account for which to get the APR\n * @return aprInfo APR information for the user for the given market\n */\n function estimateAPR(\n address market,\n address user,\n uint256 borrow,\n uint256 supply,\n uint256 xvsStaked\n ) external view returns (APRInfo memory aprInfo) {\n aprInfo.totalScore = markets[market].sumOfMembersScore - interests[market][user].score;\n\n aprInfo.xvsBalanceForScore = _xvsBalanceForScore(xvsStaked);\n Capital memory capital = _capitalForScore(aprInfo.xvsBalanceForScore, borrow, supply, market);\n\n aprInfo.capital = capital.capital;\n aprInfo.cappedSupply = capital.cappedSupply;\n aprInfo.cappedBorrow = capital.cappedBorrow;\n aprInfo.supplyCapUSD = capital.supplyCapUSD;\n aprInfo.borrowCapUSD = capital.borrowCapUSD;\n\n uint256 decimals = IERC20MetadataUpgradeable(_getUnderlying(market)).decimals();\n aprInfo.capital = aprInfo.capital * (10 ** (18 - decimals));\n\n aprInfo.userScore = Scores._calculateScore(\n aprInfo.xvsBalanceForScore,\n aprInfo.capital,\n alphaNumerator,\n alphaDenominator\n );\n\n aprInfo.totalScore = aprInfo.totalScore + aprInfo.userScore;\n\n (aprInfo.supplyAPR, aprInfo.borrowAPR) = _calculateUserAPR(\n market,\n supply,\n borrow,\n aprInfo.cappedSupply,\n aprInfo.cappedBorrow,\n aprInfo.userScore,\n aprInfo.totalScore\n );\n }\n\n /**\n * @notice Distributes income from market since last distribution\n * @param vToken the market for which to distribute the income\n * @custom:error Throw MarketNotSupported if market is not supported\n */\n function accrueInterest(address vToken) public {\n Market storage market = markets[vToken];\n\n if (!market.exists) revert MarketNotSupported();\n\n address underlying = _getUnderlying(vToken);\n\n IPrimeLiquidityProvider _primeLiquidityProvider = IPrimeLiquidityProvider(primeLiquidityProvider);\n _primeLiquidityProvider.accrueTokens(underlying);\n uint256 totalAccruedInPLP = _primeLiquidityProvider.tokenAmountAccrued(underlying);\n uint256 unreleasedPLPAccruedInterest = totalAccruedInPLP - unreleasedPLPIncome[underlying];\n uint256 distributionIncome = unreleasedPLPAccruedInterest;\n\n if (distributionIncome == 0) {\n return;\n }\n\n unreleasedPLPIncome[underlying] = totalAccruedInPLP;\n\n uint256 delta;\n if (market.sumOfMembersScore != 0) {\n delta = ((distributionIncome * EXP_SCALE) / market.sumOfMembersScore);\n }\n\n market.rewardIndex += delta;\n }\n\n /**\n * @notice Returns boosted interest accrued for a user\n * @param vToken the market for which to fetch the accrued interest\n * @param user the account for which to get the accrued interest\n * @return interestAccrued the number of underlying tokens accrued by the user since the last accrual\n */\n function getInterestAccrued(address vToken, address user) public returns (uint256) {\n accrueInterest(vToken);\n\n return _interestAccrued(vToken, user);\n }\n\n /**\n * @notice accrues interest and updates score of all markets for an user\n * @param user the account address for which to accrue interest and update score\n */\n function _accrueInterestAndUpdateScore(address user) internal {\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n for (uint256 i; i < marketsLength; ) {\n address market = allMarkets[i];\n _executeBoost(user, market);\n _updateScore(user, market);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Initializes all the markets for the user when a prime token is minted\n * @param account the account address for which markets needs to be initialized\n */\n function _initializeMarkets(address account) internal {\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n for (uint256 i; i < marketsLength; ) {\n address market = allMarkets[i];\n accrueInterest(market);\n\n interests[market][account].rewardIndex = markets[market].rewardIndex;\n\n uint256 score = _calculateScore(market, account);\n interests[market][account].score = score;\n markets[market].sumOfMembersScore = markets[market].sumOfMembersScore + score;\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice calculate the current score of user\n * @param market the market for which to calculate the score\n * @param user the account for which to calculate the score\n * @return score the score of the user\n */\n function _calculateScore(address market, address user) internal returns (uint256) {\n uint256 xvsBalanceForScore = _xvsBalanceForScore(_xvsBalanceOfUser(user));\n\n IVToken vToken = IVToken(market);\n uint256 borrow = vToken.borrowBalanceStored(user);\n uint256 exchangeRate = vToken.exchangeRateStored();\n uint256 balanceOfAccount = vToken.balanceOf(user);\n uint256 supply = (exchangeRate * balanceOfAccount) / EXP_SCALE;\n\n address xvsToken = IXVSVault(xvsVault).xvsAddress();\n oracle.updateAssetPrice(xvsToken);\n oracle.updatePrice(market);\n\n Capital memory capital = _capitalForScore(xvsBalanceForScore, borrow, supply, market);\n\n uint256 decimals = IERC20MetadataUpgradeable(_getUnderlying(market)).decimals();\n\n capital.capital = capital.capital * (10 ** (18 - decimals));\n\n return Scores._calculateScore(xvsBalanceForScore, capital.capital, alphaNumerator, alphaDenominator);\n }\n\n /**\n * @notice To transfer the accrued interest to user\n * @param vToken the market for which to claim\n * @param user the account for which to get the accrued interest\n * @return amount the amount of tokens transferred to the user\n * @custom:event Emits InterestClaimed event\n */\n function _claimInterest(address vToken, address user) internal returns (uint256) {\n uint256 amount = getInterestAccrued(vToken, user);\n amount += interests[vToken][user].accrued;\n\n interests[vToken][user].rewardIndex = markets[vToken].rewardIndex;\n delete interests[vToken][user].accrued;\n\n address underlying = _getUnderlying(vToken);\n IERC20Upgradeable asset = IERC20Upgradeable(underlying);\n\n if (amount > asset.balanceOf(address(this))) {\n delete unreleasedPLPIncome[underlying];\n IPrimeLiquidityProvider(primeLiquidityProvider).releaseFunds(address(asset));\n }\n\n asset.safeTransfer(user, amount);\n\n emit InterestClaimed(user, vToken, amount);\n\n return amount;\n }\n\n /**\n * @notice Used to mint a new prime token\n * @param isIrrevocable is the tokens being issued is irrevocable\n * @param user token owner\n * @custom:error Throw IneligibleToClaim if user is not eligible to claim prime token\n * @custom:event Emits Mint event\n */\n function _mint(bool isIrrevocable, address user) internal {\n Token storage token = tokens[user];\n if (token.exists) revert IneligibleToClaim();\n\n token.exists = true;\n token.isIrrevocable = isIrrevocable;\n\n if (isIrrevocable) {\n ++totalIrrevocable;\n } else {\n ++totalRevocable;\n }\n\n if (totalIrrevocable > irrevocableLimit || totalRevocable > revocableLimit) revert InvalidLimit();\n _updateRoundAfterTokenMinted(user);\n\n emit Mint(user, isIrrevocable);\n }\n\n /**\n * @notice Used to burn a new prime token\n * @param user owner whose prime token to burn\n * @custom:error Throw UserHasNoPrimeToken if user has no prime token\n * @custom:event Emits Burn event\n */\n function _burn(address user) internal {\n Token memory token = tokens[user];\n if (!token.exists) revert UserHasNoPrimeToken();\n\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n for (uint256 i; i < marketsLength; ) {\n address market = allMarkets[i];\n _executeBoost(user, market);\n markets[market].sumOfMembersScore = markets[market].sumOfMembersScore - interests[market][user].score;\n\n delete interests[market][user].score;\n delete interests[market][user].rewardIndex;\n\n unchecked {\n ++i;\n }\n }\n\n if (token.isIrrevocable) {\n --totalIrrevocable;\n } else {\n --totalRevocable;\n }\n\n delete tokens[user].exists;\n delete tokens[user].isIrrevocable;\n\n _updateRoundAfterTokenBurned(user);\n\n emit Burn(user);\n }\n\n /**\n * @notice Used to upgrade an token\n * @param user owner whose prime token to upgrade\n * @custom:error Throw InvalidLimit if total irrevocable tokens exceeds the limit\n * @custom:event Emits TokenUpgraded event\n */\n function _upgrade(address user) internal {\n Token storage userToken = tokens[user];\n\n userToken.isIrrevocable = true;\n ++totalIrrevocable;\n --totalRevocable;\n\n if (totalIrrevocable > irrevocableLimit) revert InvalidLimit();\n\n emit TokenUpgraded(user);\n }\n\n /**\n * @notice Accrue rewards for the user. Must be called before updating score\n * @param user account for which we need to accrue rewards\n * @param vToken the market for which we need to accrue rewards\n */\n function _executeBoost(address user, address vToken) internal {\n if (!markets[vToken].exists || !tokens[user].exists) {\n return;\n }\n\n accrueInterest(vToken);\n interests[vToken][user].accrued += _interestAccrued(vToken, user);\n interests[vToken][user].rewardIndex = markets[vToken].rewardIndex;\n }\n\n /**\n * @notice Update total score of user and market. Must be called after changing account's borrow or supply balance.\n * @param user account for which we need to update score\n * @param market the market for which we need to score\n */\n function _updateScore(address user, address market) internal {\n Market storage _market = markets[market];\n if (!_market.exists || !tokens[user].exists) {\n return;\n }\n\n uint256 score = _calculateScore(market, user);\n _market.sumOfMembersScore = _market.sumOfMembersScore - interests[market][user].score + score;\n\n interests[market][user].score = score;\n }\n\n /**\n * @notice Verify new alpha arguments\n * @param _alphaNumerator numerator of alpha. If alpha is 0.5 then numerator is 1\n * @param _alphaDenominator denominator of alpha. If alpha is 0.5 then denominator is 2\n * @custom:error Throw InvalidAlphaArguments if alpha is invalid\n */\n function _checkAlphaArguments(uint128 _alphaNumerator, uint128 _alphaDenominator) internal pure {\n if (_alphaNumerator >= _alphaDenominator || _alphaNumerator == 0) {\n revert InvalidAlphaArguments();\n }\n }\n\n /**\n * @notice starts round to update scores of a particular or all markets\n */\n function _startScoreUpdateRound() internal {\n nextScoreUpdateRoundId++;\n totalScoreUpdatesRequired = totalIrrevocable + totalRevocable;\n pendingScoreUpdates = totalScoreUpdatesRequired;\n }\n\n /**\n * @notice update the required score updates when token is burned before round is completed\n */\n function _updateRoundAfterTokenBurned(address user) internal {\n if (totalScoreUpdatesRequired != 0) --totalScoreUpdatesRequired;\n\n if (pendingScoreUpdates != 0 && !isScoreUpdated[nextScoreUpdateRoundId][user]) {\n --pendingScoreUpdates;\n }\n }\n\n /**\n * @notice update the required score updates when token is minted before round is completed\n */\n function _updateRoundAfterTokenMinted(address user) internal {\n if (totalScoreUpdatesRequired != 0) isScoreUpdated[nextScoreUpdateRoundId][user] = true;\n }\n\n /**\n * @notice fetch the current XVS balance of user in the XVSVault\n * @param user the account address\n * @return xvsBalance the XVS balance of user\n */\n function _xvsBalanceOfUser(address user) internal view returns (uint256) {\n (uint256 xvs, , uint256 pendingWithdrawals) = IXVSVault(xvsVault).getUserInfo(\n xvsVaultRewardToken,\n xvsVaultPoolId,\n user\n );\n return (xvs - pendingWithdrawals);\n }\n\n /**\n * @notice calculate the current XVS balance that will be used in calculation of score\n * @param xvs the actual XVS balance of user\n * @return xvsBalanceForScore the XVS balance to use in score\n */\n function _xvsBalanceForScore(uint256 xvs) internal view returns (uint256) {\n if (xvs > MAXIMUM_XVS_CAP) {\n return MAXIMUM_XVS_CAP;\n }\n return xvs;\n }\n\n /**\n * @notice calculate the capital for calculation of score\n * @param xvs the actual XVS balance of user\n * @param borrow the borrow balance of user\n * @param supply the supply balance of user\n * @param market the market vToken address\n * @return capital the capital to use in calculation of score\n */\n function _capitalForScore(\n uint256 xvs,\n uint256 borrow,\n uint256 supply,\n address market\n ) internal view returns (Capital memory capital) {\n address xvsToken = IXVSVault(xvsVault).xvsAddress();\n\n uint256 xvsPrice = oracle.getPrice(xvsToken);\n capital.borrowCapUSD = (xvsPrice * ((xvs * markets[market].borrowMultiplier) / EXP_SCALE)) / EXP_SCALE;\n capital.supplyCapUSD = (xvsPrice * ((xvs * markets[market].supplyMultiplier) / EXP_SCALE)) / EXP_SCALE;\n\n uint256 tokenPrice = oracle.getUnderlyingPrice(market);\n uint256 supplyUSD = (tokenPrice * supply) / EXP_SCALE;\n uint256 borrowUSD = (tokenPrice * borrow) / EXP_SCALE;\n\n if (supplyUSD >= capital.supplyCapUSD) {\n supply = supplyUSD != 0 ? (supply * capital.supplyCapUSD) / supplyUSD : 0;\n }\n\n if (borrowUSD >= capital.borrowCapUSD) {\n borrow = borrowUSD != 0 ? (borrow * capital.borrowCapUSD) / borrowUSD : 0;\n }\n\n capital.capital = supply + borrow;\n capital.cappedSupply = supply;\n capital.cappedBorrow = borrow;\n }\n\n /**\n * @notice Used to get if the XVS balance is eligible for prime token\n * @param amount amount of XVS\n * @return isEligible true if the staked XVS amount is enough to consider the associated user eligible for a Prime token, false otherwise\n */\n function _isEligible(uint256 amount) internal view returns (bool) {\n if (amount >= MINIMUM_STAKED_XVS) {\n return true;\n }\n\n return false;\n }\n\n /**\n * @notice Calculate the interests accrued by the user in the market, since the last accrual\n * @param vToken the market for which to calculate the accrued interest\n * @param user the user for which to calculate the accrued interest\n * @return interestAccrued the number of underlying tokens accrued by the user since the last accrual\n */\n function _interestAccrued(address vToken, address user) internal view returns (uint256) {\n Interest memory interest = interests[vToken][user];\n uint256 index = markets[vToken].rewardIndex - interest.rewardIndex;\n\n uint256 score = interest.score;\n\n return (index * score) / EXP_SCALE;\n }\n\n /**\n * @notice Returns the underlying token associated with the VToken, or wrapped native token if the market is native market\n * @param vToken the market whose underlying token will be returned\n * @return underlying The address of the underlying token associated with the VToken, or the address of the WRAPPED_NATIVE_TOKEN token if the market is NATIVE_MARKET\n */\n function _getUnderlying(address vToken) internal view returns (address) {\n if (vToken == NATIVE_MARKET) {\n return WRAPPED_NATIVE_TOKEN;\n }\n return IVToken(vToken).underlying();\n }\n\n //////////////////////////////////////////////////\n //////////////// APR Calculation ////////////////\n ////////////////////////////////////////////////\n\n /**\n * @notice the total income that's going to be distributed in a year to prime token holders\n * @param vToken the market for which to fetch the total income that's going to distributed in a year\n * @return amount the total income\n */\n function incomeDistributionYearly(address vToken) public view returns (uint256 amount) {\n uint256 totalIncomePerBlockOrSecondFromPLP = IPrimeLiquidityProvider(primeLiquidityProvider)\n .getEffectiveDistributionSpeed(_getUnderlying(vToken));\n amount = blocksOrSecondsPerYear * totalIncomePerBlockOrSecondFromPLP;\n }\n\n /**\n * @notice used to calculate the supply and borrow APR of the user\n * @param vToken the market for which to fetch the APR\n * @param totalSupply the total token supply of the user\n * @param totalBorrow the total tokens borrowed by the user\n * @param totalCappedSupply the total token capped supply of the user\n * @param totalCappedBorrow the total capped tokens borrowed by the user\n * @param userScore the score of the user\n * @param totalScore the total market score\n * @return supplyAPR the supply APR of the user\n * @return borrowAPR the borrow APR of the user\n */\n function _calculateUserAPR(\n address vToken,\n uint256 totalSupply,\n uint256 totalBorrow,\n uint256 totalCappedSupply,\n uint256 totalCappedBorrow,\n uint256 userScore,\n uint256 totalScore\n ) internal view returns (uint256 supplyAPR, uint256 borrowAPR) {\n if (totalScore == 0) return (0, 0);\n\n uint256 userYearlyIncome = (userScore * incomeDistributionYearly(vToken)) / totalScore;\n\n uint256 totalCappedValue = totalCappedSupply + totalCappedBorrow;\n\n if (totalCappedValue == 0) return (0, 0);\n\n uint256 maximumBps = MAXIMUM_BPS;\n uint256 userSupplyIncomeYearly;\n uint256 userBorrowIncomeYearly;\n userSupplyIncomeYearly = (userYearlyIncome * totalCappedSupply) / totalCappedValue;\n userBorrowIncomeYearly = (userYearlyIncome * totalCappedBorrow) / totalCappedValue;\n supplyAPR = totalSupply == 0 ? 0 : ((userSupplyIncomeYearly * maximumBps) / totalSupply);\n borrowAPR = totalBorrow == 0 ? 0 : ((userBorrowIncomeYearly * maximumBps) / totalBorrow);\n }\n}\n" + }, + "contracts/Tokens/Prime/PrimeLiquidityProvider.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { PrimeLiquidityProviderStorageV1 } from \"./PrimeLiquidityProviderStorage.sol\";\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport { IPrimeLiquidityProvider } from \"./Interfaces/IPrimeLiquidityProvider.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PrimeLiquidityProvider\n * @author Venus\n * @notice PrimeLiquidityProvider is used to fund Prime\n */\ncontract PrimeLiquidityProvider is\n IPrimeLiquidityProvider,\n AccessControlledV8,\n PausableUpgradeable,\n MaxLoopsLimitHelper,\n PrimeLiquidityProviderStorageV1,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The default max token distribution speed\n uint256 public constant DEFAULT_MAX_DISTRIBUTION_SPEED = 1e18;\n\n /// @notice Emitted when a token distribution is initialized\n event TokenDistributionInitialized(address indexed token);\n\n /// @notice Emitted when a new token distribution speed is set\n event TokenDistributionSpeedUpdated(address indexed token, uint256 oldSpeed, uint256 newSpeed);\n\n /// @notice Emitted when a new max distribution speed for token is set\n event MaxTokenDistributionSpeedUpdated(address indexed token, uint256 oldSpeed, uint256 newSpeed);\n\n /// @notice Emitted when prime token contract address is changed\n event PrimeTokenUpdated(address indexed oldPrimeToken, address indexed newPrimeToken);\n\n /// @notice Emitted when distribution state(Index and block or second) is updated\n event TokensAccrued(address indexed token, uint256 amount);\n\n /// @notice Emitted when token is transferred to the prime contract\n event TokenTransferredToPrime(address indexed token, uint256 amount);\n\n /// @notice Emitted on sweep token success\n event SweepToken(address indexed token, address indexed to, uint256 sweepAmount);\n\n /// @notice Thrown when arguments are passed are invalid\n error InvalidArguments();\n\n /// @notice Thrown when distribution speed is greater than maxTokenDistributionSpeeds[tokenAddress]\n error InvalidDistributionSpeed(uint256 speed, uint256 maxSpeed);\n\n /// @notice Thrown when caller is not the desired caller\n error InvalidCaller();\n\n /// @notice Thrown when token is initialized\n error TokenAlreadyInitialized(address token);\n\n ///@notice Error thrown when PrimeLiquidityProvider's balance is less than sweep amount\n error InsufficientBalance(uint256 sweepAmount, uint256 balance);\n\n /// @notice Error thrown when funds transfer is paused\n error FundsTransferIsPaused();\n\n /// @notice Error thrown when accrueTokens is called for an uninitialized token\n error TokenNotInitialized(address token_);\n\n /// @notice Error thrown when argument value in setter is same as previous value\n error AddressesMustDiffer();\n\n /**\n * @notice Compares two addresses to ensure they are different\n * @param oldAddress The original address to compare\n * @param newAddress The new address to compare\n */\n modifier compareAddress(address oldAddress, address newAddress) {\n if (newAddress == oldAddress) {\n revert AddressesMustDiffer();\n }\n _;\n }\n\n /**\n * @notice Prime Liquidity Provider constructor\n * @param _timeBased A boolean indicating whether the contract is based on time or block.\n * @param _blocksPerYear total blocks per year\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(bool _timeBased, uint256 _blocksPerYear) TimeManagerV8(_timeBased, _blocksPerYear) {\n _disableInitializers();\n }\n\n /**\n * @notice PrimeLiquidityProvider initializer\n * @dev Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n * @param tokens_ Array of addresses of the tokens\n * @param distributionSpeeds_ New distribution speeds for tokens\n * @param loopsLimit_ Maximum number of loops allowed in a single transaction\n * @custom:error Throw InvalidArguments on different length of tokens and speeds array\n */\n function initialize(\n address accessControlManager_,\n address[] calldata tokens_,\n uint256[] calldata distributionSpeeds_,\n uint256[] calldata maxDistributionSpeeds_,\n uint256 loopsLimit_\n ) external initializer {\n _ensureZeroAddress(accessControlManager_);\n\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n _setMaxLoopsLimit(loopsLimit_);\n\n uint256 numTokens = tokens_.length;\n _ensureMaxLoops(numTokens);\n\n if ((numTokens != distributionSpeeds_.length) || (numTokens != maxDistributionSpeeds_.length)) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < numTokens; ) {\n _initializeToken(tokens_[i]);\n _setMaxTokenDistributionSpeed(tokens_[i], maxDistributionSpeeds_[i]);\n _setTokenDistributionSpeed(tokens_[i], distributionSpeeds_[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Initialize the distribution of the token\n * @param tokens_ Array of addresses of the tokens to be intialized\n * @custom:access Only Governance\n */\n function initializeTokens(address[] calldata tokens_) external onlyOwner {\n uint256 tokensLength = tokens_.length;\n _ensureMaxLoops(tokensLength);\n\n for (uint256 i; i < tokensLength; ) {\n _initializeToken(tokens_[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Pause fund transfer of tokens to Prime contract\n * @custom:access Controlled by ACM\n */\n function pauseFundsTransfer() external {\n _checkAccessAllowed(\"pauseFundsTransfer()\");\n _pause();\n }\n\n /**\n * @notice Resume fund transfer of tokens to Prime contract\n * @custom:access Controlled by ACM\n */\n function resumeFundsTransfer() external {\n _checkAccessAllowed(\"resumeFundsTransfer()\");\n _unpause();\n }\n\n /**\n * @notice Set distribution speed (amount of token distribute per block or second)\n * @param tokens_ Array of addresses of the tokens\n * @param distributionSpeeds_ New distribution speeds for tokens\n * @custom:access Controlled by ACM\n * @custom:error Throw InvalidArguments on different length of tokens and speeds array\n */\n function setTokensDistributionSpeed(address[] calldata tokens_, uint256[] calldata distributionSpeeds_) external {\n _checkAccessAllowed(\"setTokensDistributionSpeed(address[],uint256[])\");\n uint256 numTokens = tokens_.length;\n _ensureMaxLoops(numTokens);\n\n if (numTokens != distributionSpeeds_.length) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < numTokens; ) {\n _ensureTokenInitialized(tokens_[i]);\n _setTokenDistributionSpeed(tokens_[i], distributionSpeeds_[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set max distribution speed for token (amount of maximum token distribute per block or second)\n * @param tokens_ Array of addresses of the tokens\n * @param maxDistributionSpeeds_ New distribution speeds for tokens\n * @custom:access Controlled by ACM\n * @custom:error Throw InvalidArguments on different length of tokens and speeds array\n */\n function setMaxTokensDistributionSpeed(\n address[] calldata tokens_,\n uint256[] calldata maxDistributionSpeeds_\n ) external {\n _checkAccessAllowed(\"setMaxTokensDistributionSpeed(address[],uint256[])\");\n uint256 numTokens = tokens_.length;\n _ensureMaxLoops(numTokens);\n\n if (numTokens != maxDistributionSpeeds_.length) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < numTokens; ) {\n _setMaxTokenDistributionSpeed(tokens_[i], maxDistributionSpeeds_[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set the prime token contract address\n * @param prime_ The new address of the prime token contract\n * @custom:event Emits PrimeTokenUpdated event\n * @custom:access Only owner\n */\n function setPrimeToken(address prime_) external onlyOwner compareAddress(prime, prime_) {\n _ensureZeroAddress(prime_);\n\n emit PrimeTokenUpdated(prime, prime_);\n prime = prime_;\n }\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param loopsLimit Limit for the max loops can execute at a time\n * @custom:event Emits MaxLoopsLimitUpdated event on success\n * @custom:access Controlled by ACM\n */\n function setMaxLoopsLimit(uint256 loopsLimit) external {\n _checkAccessAllowed(\"setMaxLoopsLimit(uint256)\");\n _setMaxLoopsLimit(loopsLimit);\n }\n\n /**\n * @notice Claim all the token accrued till last block or second\n * @param token_ The token to release to the Prime contract\n * @custom:event Emits TokenTransferredToPrime event\n * @custom:error Throw InvalidArguments on Zero address(token)\n * @custom:error Throw FundsTransferIsPaused is paused\n * @custom:error Throw InvalidCaller if the sender is not the Prime contract\n */\n function releaseFunds(address token_) external {\n address _prime = prime;\n if (msg.sender != _prime) revert InvalidCaller();\n if (paused()) {\n revert FundsTransferIsPaused();\n }\n\n accrueTokens(token_);\n uint256 accruedAmount = _tokenAmountAccrued[token_];\n delete _tokenAmountAccrued[token_];\n\n emit TokenTransferredToPrime(token_, accruedAmount);\n\n IERC20Upgradeable(token_).safeTransfer(_prime, accruedAmount);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to user\n * @param token_ The address of the ERC-20 token to sweep\n * @param to_ The address of the recipient\n * @param amount_ The amount of tokens needs to transfer\n * @custom:event Emits SweepToken event\n * @custom:error Throw InsufficientBalance if amount_ is greater than the available balance of the token in the contract\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token_, address to_, uint256 amount_) external onlyOwner {\n uint256 balance = token_.balanceOf(address(this));\n if (amount_ > balance) {\n revert InsufficientBalance(amount_, balance);\n }\n\n emit SweepToken(address(token_), to_, amount_);\n\n token_.safeTransfer(to_, amount_);\n }\n\n /**\n * @notice Get rewards per block or second for token\n * @param token_ Address of the token\n * @return speed returns the per block or second reward\n */\n function getEffectiveDistributionSpeed(address token_) external view returns (uint256) {\n uint256 distributionSpeed = tokenDistributionSpeeds[token_];\n uint256 balance = IERC20Upgradeable(token_).balanceOf(address(this));\n uint256 accrued = _tokenAmountAccrued[token_];\n\n if (balance > accrued) {\n return distributionSpeed;\n }\n\n return 0;\n }\n\n /**\n * @notice Accrue token by updating the distribution state\n * @param token_ Address of the token\n * @custom:event Emits TokensAccrued event\n */\n function accrueTokens(address token_) public {\n _ensureZeroAddress(token_);\n\n _ensureTokenInitialized(token_);\n\n uint256 blockNumberOrSecond = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrSeconds;\n unchecked {\n deltaBlocksOrSeconds = blockNumberOrSecond - lastAccruedBlockOrSecond[token_];\n }\n\n if (deltaBlocksOrSeconds != 0) {\n uint256 distributionSpeed = tokenDistributionSpeeds[token_];\n uint256 balance = IERC20Upgradeable(token_).balanceOf(address(this));\n\n uint256 balanceDiff = balance - _tokenAmountAccrued[token_];\n if (distributionSpeed != 0 && balanceDiff != 0) {\n uint256 accruedSinceUpdate = deltaBlocksOrSeconds * distributionSpeed;\n uint256 tokenAccrued = (balanceDiff <= accruedSinceUpdate ? balanceDiff : accruedSinceUpdate);\n\n _tokenAmountAccrued[token_] += tokenAccrued;\n emit TokensAccrued(token_, tokenAccrued);\n }\n\n lastAccruedBlockOrSecond[token_] = blockNumberOrSecond;\n }\n }\n\n /**\n * @notice Get the last accrued block or second for token\n * @param token_ Address of the token\n * @return blockNumberOrSecond returns the last accrued block or second\n */\n function lastAccruedBlock(address token_) external view returns (uint256) {\n return lastAccruedBlockOrSecond[token_];\n }\n\n /**\n * @notice Get the tokens accrued\n * @param token_ Address of the token\n * @return returns the amount of accrued tokens for the token provided\n */\n function tokenAmountAccrued(address token_) external view returns (uint256) {\n return _tokenAmountAccrued[token_];\n }\n\n /**\n * @notice Initialize the distribution of the token\n * @param token_ Address of the token to be intialized\n * @custom:event Emits TokenDistributionInitialized event\n * @custom:error Throw TokenAlreadyInitialized if token is already initialized\n */\n function _initializeToken(address token_) internal {\n _ensureZeroAddress(token_);\n uint256 blockNumberOrSecond = getBlockNumberOrTimestamp();\n uint256 initializedBlockOrSecond = lastAccruedBlockOrSecond[token_];\n\n if (initializedBlockOrSecond != 0) {\n revert TokenAlreadyInitialized(token_);\n }\n\n /*\n * Update token state block number or second\n */\n lastAccruedBlockOrSecond[token_] = blockNumberOrSecond;\n\n emit TokenDistributionInitialized(token_);\n }\n\n /**\n * @notice Set distribution speed (amount of token distribute per block or second)\n * @param token_ Address of the token\n * @param distributionSpeed_ New distribution speed for token\n * @custom:event Emits TokenDistributionSpeedUpdated event\n * @custom:error Throw InvalidDistributionSpeed if speed is greater than max speed\n */\n function _setTokenDistributionSpeed(address token_, uint256 distributionSpeed_) internal {\n uint256 maxDistributionSpeed = maxTokenDistributionSpeeds[token_];\n if (maxDistributionSpeed == 0) {\n maxTokenDistributionSpeeds[token_] = maxDistributionSpeed = DEFAULT_MAX_DISTRIBUTION_SPEED;\n }\n\n if (distributionSpeed_ > maxDistributionSpeed) {\n revert InvalidDistributionSpeed(distributionSpeed_, maxDistributionSpeed);\n }\n\n uint256 oldDistributionSpeed = tokenDistributionSpeeds[token_];\n if (oldDistributionSpeed != distributionSpeed_) {\n // Distribution speed updated so let's update distribution state to ensure that\n // 1. Token accrued properly for the old speed, and\n // 2. Token accrued at the new speed starts after this block or second.\n accrueTokens(token_);\n\n // Update speed\n tokenDistributionSpeeds[token_] = distributionSpeed_;\n\n emit TokenDistributionSpeedUpdated(token_, oldDistributionSpeed, distributionSpeed_);\n }\n }\n\n /**\n * @notice Set max distribution speed (amount of maximum token distribute per block or second)\n * @param token_ Address of the token\n * @param maxDistributionSpeed_ New max distribution speed for token\n * @custom:event Emits MaxTokenDistributionSpeedUpdated event\n */\n function _setMaxTokenDistributionSpeed(address token_, uint256 maxDistributionSpeed_) internal {\n emit MaxTokenDistributionSpeedUpdated(token_, tokenDistributionSpeeds[token_], maxDistributionSpeed_);\n maxTokenDistributionSpeeds[token_] = maxDistributionSpeed_;\n }\n\n /**\n * @notice Revert on non initialized token\n * @param token_ Token Address to be verified for\n */\n function _ensureTokenInitialized(address token_) internal view {\n uint256 lastBlockOrSecondAccrued = lastAccruedBlockOrSecond[token_];\n\n if (lastBlockOrSecondAccrued == 0) {\n revert TokenNotInitialized(token_);\n }\n }\n\n /**\n * @notice Revert on zero address\n * @param address_ Address to be verified\n */\n function _ensureZeroAddress(address address_) internal pure {\n if (address_ == address(0)) {\n revert InvalidArguments();\n }\n }\n}\n" + }, + "contracts/Tokens/Prime/PrimeLiquidityProviderStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title PrimeLiquidityProviderStorageV1\n * @author Venus\n * @notice Storage for Prime Liquidity Provider\n */\ncontract PrimeLiquidityProviderStorageV1 {\n /// @notice Address of the Prime contract\n address public prime;\n\n /// @notice The rate at which token is distributed (per block or second)\n mapping(address => uint256) public tokenDistributionSpeeds;\n\n /// @notice The max token distribution speed for token\n mapping(address => uint256) public maxTokenDistributionSpeeds;\n\n /// @notice The block or second till which rewards are distributed for an asset\n mapping(address => uint256) public lastAccruedBlockOrSecond;\n\n /// @notice The token accrued but not yet transferred to prime contract\n mapping(address => uint256) internal _tokenAmountAccrued;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n uint256[45] private __gap;\n}\n" + }, + "contracts/Tokens/Prime/PrimeStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\n/**\n * @title PrimeStorageV1\n * @author Venus\n * @notice Storage for Prime Token\n */\ncontract PrimeStorageV1 {\n struct Token {\n bool exists;\n bool isIrrevocable;\n }\n\n struct Market {\n uint256 supplyMultiplier;\n uint256 borrowMultiplier;\n uint256 rewardIndex;\n uint256 sumOfMembersScore;\n bool exists;\n }\n\n struct Interest {\n uint256 accrued;\n uint256 score;\n uint256 rewardIndex;\n }\n\n struct PendingReward {\n address vToken;\n address rewardToken;\n uint256 amount;\n }\n\n /// @notice Base unit for computations, usually used in scaling (multiplications, divisions)\n uint256 internal constant EXP_SCALE = 1e18;\n\n /// @notice maximum BPS = 100%\n uint256 internal constant MAXIMUM_BPS = 1e4;\n\n /// @notice Mapping to get prime token's metadata\n mapping(address => Token) public tokens;\n\n /// @notice Tracks total irrevocable tokens minted\n uint256 public totalIrrevocable;\n\n /// @notice Tracks total revocable tokens minted\n uint256 public totalRevocable;\n\n /// @notice Indicates maximum revocable tokens that can be minted\n uint256 public revocableLimit;\n\n /// @notice Indicates maximum irrevocable tokens that can be minted\n uint256 public irrevocableLimit;\n\n /// @notice Tracks when prime token eligible users started staking for claiming prime token\n mapping(address => uint256) public stakedAt;\n\n /// @notice vToken to market configuration\n mapping(address => Market) public markets;\n\n /// @notice vToken to user to user index\n mapping(address => mapping(address => Interest)) public interests;\n\n /// @notice A list of boosted markets\n address[] internal _allMarkets;\n\n /// @notice numerator of alpha. Ex: if alpha is 0.5 then this will be 1\n uint128 public alphaNumerator;\n\n /// @notice denominator of alpha. Ex: if alpha is 0.5 then this will be 2\n uint128 public alphaDenominator;\n\n /// @notice address of XVS vault\n address public xvsVault;\n\n /// @notice address of XVS vault reward token\n address public xvsVaultRewardToken;\n\n /// @notice address of XVS vault pool id\n uint256 public xvsVaultPoolId;\n\n /// @notice mapping to check if a account's score was updated in the round\n mapping(uint256 => mapping(address => bool)) public isScoreUpdated;\n\n /// @notice unique id for next round\n uint256 public nextScoreUpdateRoundId;\n\n /// @notice total number of accounts whose score needs to be updated\n uint256 public totalScoreUpdatesRequired;\n\n /// @notice total number of accounts whose score is yet to be updated\n uint256 public pendingScoreUpdates;\n\n /// @notice mapping used to find if an asset is part of prime markets\n mapping(address => address) public vTokenForAsset;\n\n /// @notice Address of core pool comptroller contract\n address internal corePoolComptroller;\n\n /// @notice unreleased income from PLP that's already distributed to prime holders\n /// @dev mapping of asset address => amount\n mapping(address => uint256) public unreleasedPLPIncome;\n\n /// @notice The address of PLP contract\n address public primeLiquidityProvider;\n\n /// @notice The address of ResilientOracle contract\n ResilientOracleInterface public oracle;\n\n /// @notice The address of PoolRegistry contract\n address public poolRegistry;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n uint256[26] private __gap;\n}\n" + }, + "contracts/Tokens/test/IERC20NonStandard.sol": { + "content": "pragma solidity 0.8.25;\n\n/**\n * @title EIP20NonStandardInterface\n * @dev Version of BEP20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ninterface IERC20NonStandard {\n /**\n * @notice Get the total number of tokens in circulation\n * @return The supply of tokens\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @notice Gets the balance of the specified address\n * @param owner The address from which the balance will be retrieved\n * @return balance of the owner\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the BEP-20 specification\n /// !!!!!!!!!!!!!!\n ///\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n */\n function transfer(address dst, uint256 amount) external;\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the BEP-20 specification\n /// !!!!!!!!!!!!!!\n ///\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n */\n function transferFrom(address src, address dst, uint256 amount) external;\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved\n * @return success Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external returns (bool success);\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return remaining The number of tokens allowed to be spent\n */\n function allowance(address owner, address spender) external view returns (uint256 remaining);\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n}\n" + }, + "contracts/Tokens/VAI/IVAI.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\n// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico\n\npragma solidity 0.8.25;\n\ninterface IVAI {\n // --- Auth ---\n function wards(address) external view returns (uint256);\n function rely(address guy) external;\n function deny(address guy) external;\n\n // --- BEP20 Data ---\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function version() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address) external view returns (uint256);\n function allowance(address, address) external view returns (uint256);\n function nonces(address) external view returns (uint256);\n\n event Approval(address indexed src, address indexed guy, uint256 wad);\n event Transfer(address indexed src, address indexed dst, uint256 wad);\n\n // --- EIP712 niceties ---\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n // bytes32 public constant PERMIT_TYPEHASH = keccak256(\"Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)\");\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n\n // --- Token ---\n function transfer(address dst, uint256 wad) external returns (bool);\n function transferFrom(address src, address dst, uint256 wad) external returns (bool);\n function mint(address usr, uint256 wad) external;\n function burn(address usr, uint256 wad) external;\n function approve(address usr, uint256 wad) external returns (bool);\n\n // --- Alias ---\n function push(address usr, uint256 wad) external;\n function pull(address usr, uint256 wad) external;\n function move(address src, address dst, uint256 wad) external;\n\n // --- Approve by signature ---\n function permit(\n address holder,\n address spender,\n uint256 nonce,\n uint256 expiry,\n bool allowed,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "contracts/Tokens/VAI/VAIController.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\nimport { VAIControllerErrorReporter } from \"../../Utils/ErrorReporter.sol\";\nimport { Exponential } from \"../../Utils/Exponential.sol\";\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../VTokens/VToken.sol\";\nimport { VAIUnitroller } from \"./VAIUnitroller.sol\";\nimport { VAIControllerInterface } from \"./VAIControllerInterface.sol\";\nimport { IVAI } from \"./IVAI.sol\";\nimport { IPrime } from \"../Prime/IPrime.sol\";\nimport { VTokenInterface } from \"../VTokens/VTokenInterfaces.sol\";\nimport { VAIControllerStorageG4 } from \"./VAIControllerStorage.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\n\n/**\n * @title VAI Comptroller\n * @author Venus\n * @notice This is the implementation contract for the VAIUnitroller proxy\n */\ncontract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAIControllerErrorReporter, Exponential {\n /// @notice Initial index used in interest computations\n uint256 public constant INITIAL_VAI_MINT_INDEX = 1e18;\n\n /// poolId for core Pool\n uint96 public constant CORE_POOL_ID = 0;\n\n /// @notice Emitted when Comptroller is changed\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\n\n /// @notice Emitted when mint for prime holder is changed\n event MintOnlyForPrimeHolder(bool previousMintEnabledOnlyForPrimeHolder, bool newMintEnabledOnlyForPrimeHolder);\n\n /// @notice Emitted when Prime is changed\n event NewPrime(address oldPrime, address newPrime);\n\n /// @notice Event emitted when VAI is minted\n event MintVAI(address minter, uint256 mintVAIAmount);\n\n /// @notice Event emitted when VAI is repaid\n event RepayVAI(address payer, address borrower, uint256 repayVAIAmount);\n\n /// @notice Event emitted when a borrow is liquidated\n event LiquidateVAI(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n address vTokenCollateral,\n uint256 seizeTokens\n );\n\n /// @notice Emitted when treasury guardian is changed\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\n\n /// @notice Emitted when treasury address is changed\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\n\n /// @notice Emitted when treasury percent is changed\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\n\n /// @notice Event emitted when VAIs are minted and fee are transferred\n event MintFee(address minter, uint256 feeAmount);\n\n /// @notice Emiitted when VAI base rate is changed\n event NewVAIBaseRate(uint256 oldBaseRateMantissa, uint256 newBaseRateMantissa);\n\n /// @notice Emiitted when VAI float rate is changed\n event NewVAIFloatRate(uint256 oldFloatRateMantissa, uint256 newFlatRateMantissa);\n\n /// @notice Emiitted when VAI receiver address is changed\n event NewVAIReceiver(address oldReceiver, address newReceiver);\n\n /// @notice Emiitted when VAI mint cap is changed\n event NewVAIMintCap(uint256 oldMintCap, uint256 newMintCap);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\n\n /// @notice Emitted when VAI token address is changed by admin\n event NewVaiToken(address oldVaiToken, address newVaiToken);\n\n function initialize() external onlyAdmin {\n require(vaiMintIndex == 0, \"already initialized\");\n\n vaiMintIndex = INITIAL_VAI_MINT_INDEX;\n accrualBlockNumber = getBlockNumber();\n mintCap = type(uint256).max;\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n }\n\n function _become(VAIUnitroller unitroller) external {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can change brains\");\n require(unitroller._acceptImplementation() == 0, \"change not authorized\");\n }\n\n /**\n * @notice The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance.\n * The amount minted must be less than the user's Account Liquidity and the mint vai limit.\n * @dev If the Comptroller address is not set, minting is a no-op and the function returns the success code.\n * @param mintVAIAmount The amount of the VAI to be minted.\n * @return 0 on success, otherwise an error code\n */\n // solhint-disable-next-line code-complexity\n function mintVAI(uint256 mintVAIAmount) external nonReentrant returns (uint256) {\n if (address(comptroller) == address(0)) {\n return uint256(Error.NO_ERROR);\n }\n\n require(comptroller.userPoolId(msg.sender) == CORE_POOL_ID, \"VAI mint only allowed in the core Pool\");\n\n _ensureNonzeroAmount(mintVAIAmount);\n _ensureNotPaused();\n accrueVAIInterest();\n\n uint256 err;\n address minter = msg.sender;\n address _vai = vai;\n uint256 vaiTotalSupply = IVAI(_vai).totalSupply();\n\n uint256 vaiNewTotalSupply = add_(vaiTotalSupply, mintVAIAmount);\n require(vaiNewTotalSupply <= mintCap, \"mint cap reached\");\n\n _updateProtectionStateForEnteredMarkets(minter);\n\n uint256 accountMintableVAI;\n (err, accountMintableVAI) = getMintableVAI(minter);\n require(err == uint256(Error.NO_ERROR), \"could not compute mintable amount\");\n\n // check that user have sufficient mintableVAI balance\n require(mintVAIAmount <= accountMintableVAI, \"minting more than allowed\");\n\n // Calculate the minted balance based on interest index\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\n\n if (totalMintedVAI > 0) {\n uint256 repayAmount = getVAIRepayAmount(minter);\n uint256 remainedAmount = sub_(repayAmount, totalMintedVAI);\n pastVAIInterest[minter] = add_(pastVAIInterest[minter], remainedAmount);\n totalMintedVAI = repayAmount;\n }\n\n uint256 accountMintVAINew = add_(totalMintedVAI, mintVAIAmount);\n err = comptroller.setMintedVAIOf(minter, accountMintVAINew);\n require(err == uint256(Error.NO_ERROR), \"comptroller rejection\");\n\n uint256 remainedAmount;\n if (treasuryPercent != 0) {\n uint256 feeAmount = div_(mul_(mintVAIAmount, treasuryPercent), 1e18);\n remainedAmount = sub_(mintVAIAmount, feeAmount);\n IVAI(_vai).mint(treasuryAddress, feeAmount);\n\n emit MintFee(minter, feeAmount);\n } else {\n remainedAmount = mintVAIAmount;\n }\n\n IVAI(_vai).mint(minter, remainedAmount);\n vaiMinterInterestIndex[minter] = vaiMintIndex;\n\n emit MintVAI(minter, remainedAmount);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice The repay function transfers VAI interest into the protocol and burns the rest,\n * reducing the borrower's borrow balance. Before repaying VAI, users must first approve\n * VAIController to access their VAI balance.\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\n * @param amount The amount of VAI to be repaid.\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function repayVAI(uint256 amount) external nonReentrant returns (uint256, uint256) {\n return _repayVAI(msg.sender, amount);\n }\n\n /**\n * @notice The repay on behalf function transfers VAI interest into the protocol and burns the rest,\n * reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower).\n * Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\n * @param borrower The account to repay the debt for.\n * @param amount The amount of VAI to be repaid.\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function repayVAIBehalf(address borrower, uint256 amount) external nonReentrant returns (uint256, uint256) {\n _ensureNonzeroAddress(borrower);\n return _repayVAI(borrower, amount);\n }\n\n /**\n * @dev Checks the parameters and the protocol state, accrues interest, and invokes repayVAIFresh.\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\n * @param borrower The account to repay the debt for.\n * @param amount The amount of VAI to be repaid.\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function _repayVAI(address borrower, uint256 amount) internal returns (uint256, uint256) {\n if (address(comptroller) == address(0)) {\n return (0, 0);\n }\n _ensureNonzeroAmount(amount);\n _ensureNotPaused();\n\n accrueVAIInterest();\n return repayVAIFresh(msg.sender, borrower, amount);\n }\n\n /**\n * @dev Repay VAI, expecting interest to be accrued\n * @dev Borrowed VAIs are repaid by another user (possibly the borrower).\n * @param payer the account paying off the VAI\n * @param borrower the account with the debt being payed off\n * @param repayAmount the amount of VAI being repaid\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function repayVAIFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256, uint256) {\n (uint256 burn, uint256 partOfCurrentInterest, uint256 partOfPastInterest) = getVAICalculateRepayAmount(\n borrower,\n repayAmount\n );\n\n IVAI _vai = IVAI(vai);\n _vai.burn(payer, burn);\n bool success = _vai.transferFrom(payer, receiver, partOfCurrentInterest);\n require(success == true, \"failed to transfer VAI fee\");\n\n uint256 vaiBalanceBorrower = comptroller.mintedVAIs(borrower);\n\n uint256 accountVAINew = sub_(sub_(vaiBalanceBorrower, burn), partOfPastInterest);\n pastVAIInterest[borrower] = sub_(pastVAIInterest[borrower], partOfPastInterest);\n\n uint256 error = comptroller.setMintedVAIOf(borrower, accountVAINew);\n // We have to revert upon error since side-effects already happened at this point\n require(error == uint256(Error.NO_ERROR), \"comptroller rejection\");\n\n uint256 repaidAmount = add_(burn, partOfCurrentInterest);\n emit RepayVAI(payer, borrower, repaidAmount);\n\n return (uint256(Error.NO_ERROR), repaidAmount);\n }\n\n /**\n * @notice The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of vai to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function liquidateVAI(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external nonReentrant returns (uint256, uint256) {\n _ensureNotPaused();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\n }\n\n // liquidateVAIFresh emits borrow-specific logs on errors, so we don't need to\n return liquidateVAIFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral by repay borrowers VAI.\n * The collateral seized is transferred to the liquidator.\n * @dev If the Comptroller address is not set, liquidation is a no-op and the function returns the success code.\n * @param liquidator The address repaying the VAI and seizing collateral\n * @param borrower The borrower of this VAI to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the VAI to repay\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function liquidateVAIFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) internal returns (uint256, uint256) {\n if (address(comptroller) != address(0)) {\n accrueVAIInterest();\n\n /* Fail if liquidate not allowed */\n uint256 allowed = comptroller.liquidateBorrowAllowed(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n repayAmount\n );\n if (allowed != 0) {\n return (failOpaque(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n //if (vTokenCollateral.accrualBlockNumber() != accrualBlockNumber) {\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n /* Fail if repayVAI fails */\n (uint256 repayBorrowError, uint256 actualRepayAmount) = repayVAIFresh(liquidator, borrower, repayAmount);\n if (repayBorrowError != uint256(Error.NO_ERROR)) {\n return (fail(Error(repayBorrowError), FailureInfo.VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateVAICalculateSeizeTokens(\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(\n amountSeizeError == uint256(Error.NO_ERROR),\n \"VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\"\n );\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"VAI_LIQUIDATE_SEIZE_TOO_MUCH\");\n\n uint256 seizeError;\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\n require(seizeError == uint256(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateVAI(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n\n /* We call the defense hook */\n comptroller.liquidateBorrowVerify(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n actualRepayAmount,\n seizeTokens\n );\n\n return (uint256(Error.NO_ERROR), actualRepayAmount);\n }\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Sets a new comptroller\n * @dev Admin function to set a new comptroller\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptroller(ComptrollerInterface comptroller_) external returns (uint256) {\n // Check caller is admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\n }\n\n ComptrollerInterface oldComptroller = comptroller;\n comptroller = comptroller_;\n emit NewComptroller(oldComptroller, comptroller_);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the prime token contract address\n * @param prime_ The new address of the prime token contract\n */\n function setPrimeToken(address prime_) external onlyAdmin {\n emit NewPrime(prime, prime_);\n prime = prime_;\n }\n\n /**\n * @notice Set the VAI token contract address\n * @param vai_ The new address of the VAI token contract\n */\n function setVAIToken(address vai_) external onlyAdmin {\n emit NewVaiToken(vai, vai_);\n vai = vai_;\n }\n\n /**\n * @notice Toggle mint only for prime holder\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function toggleOnlyPrimeHolderMint() external returns (uint256) {\n _ensureAllowed(\"toggleOnlyPrimeHolderMint()\");\n\n if (!mintEnabledOnlyForPrimeHolder && prime == address(0)) {\n return uint256(Error.REJECTION);\n }\n\n emit MintOnlyForPrimeHolder(mintEnabledOnlyForPrimeHolder, !mintEnabledOnlyForPrimeHolder);\n mintEnabledOnlyForPrimeHolder = !mintEnabledOnlyForPrimeHolder;\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account total supply balance.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountAmountLocalVars {\n uint256 oErr;\n MathError mErr;\n uint256 sumSupply;\n uint256 marketSupply;\n uint256 sumBorrowPlusEffects;\n uint256 vTokenBalance;\n uint256 borrowBalance;\n uint256 exchangeRateMantissa;\n uint256 collateralPriceMantissa;\n uint256 debtPriceMantissa;\n Exp exchangeRate;\n Exp collateralPrice;\n Exp debtPrice;\n Exp tokensToDenom;\n }\n\n /**\n * @notice Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate\n * If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\n * @param minter The account to check mintable VAI\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\n * @return Mintable amount (with 18 decimals)\n */\n // solhint-disable-next-line code-complexity\n function getMintableVAI(address minter) public view returns (uint256, uint256) {\n if (mintEnabledOnlyForPrimeHolder && !IPrime(prime).isUserPrimeHolder(minter)) {\n return (uint256(Error.REJECTION), 0);\n }\n\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\n IDeviationBoundedOracle boundedOracle = comptroller.deviationBoundedOracle();\n\n AccountAmountLocalVars memory vars; // Holds all our calculation results\n\n uint256 accountMintableVAI;\n uint256 i;\n\n /**\n * We use this formula to calculate mintable VAI amount.\n * totalSupplyAmount * VAIMintRate - (totalBorrowAmount + mintedVAIOf)\n */\n uint256 marketsCount = enteredMarkets.length;\n for (i = 0; i < marketsCount; i++) {\n (vars.oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = enteredMarkets[i]\n .getAccountSnapshot(minter);\n if (vars.oErr != 0) {\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\n return (uint256(Error.SNAPSHOT_ERROR), 0);\n }\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n // Get bounded prices: collateral price for supply valuation, debt price for borrow valuation\n (vars.collateralPriceMantissa, vars.debtPriceMantissa) = boundedOracle.getBoundedPricesView(\n address(enteredMarkets[i])\n );\n if (vars.collateralPriceMantissa == 0 || vars.debtPriceMantissa == 0) {\n return (uint256(Error.PRICE_ERROR), 0);\n }\n vars.collateralPrice = Exp({ mantissa: vars.collateralPriceMantissa });\n vars.debtPrice = Exp({ mantissa: vars.debtPriceMantissa });\n\n (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.collateralPrice);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n // marketSupply = tokensToDenom * vTokenBalance\n (vars.mErr, vars.marketSupply) = mulScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n (, uint256 collateralFactorMantissa, , , , , ) = comptroller.markets(address(enteredMarkets[i]));\n (vars.mErr, vars.marketSupply) = mulUInt(vars.marketSupply, collateralFactorMantissa);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, vars.marketSupply) = divUInt(vars.marketSupply, 1e18);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, vars.sumSupply) = addUInt(vars.sumSupply, vars.marketSupply);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n // sumBorrowPlusEffects += debtPrice * borrowBalance\n (vars.mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(\n vars.debtPrice,\n vars.borrowBalance,\n vars.sumBorrowPlusEffects\n );\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n }\n\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\n uint256 repayAmount = 0;\n\n if (totalMintedVAI > 0) {\n repayAmount = getVAIRepayAmount(minter);\n }\n\n (vars.mErr, vars.sumBorrowPlusEffects) = addUInt(vars.sumBorrowPlusEffects, repayAmount);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, accountMintableVAI) = mulUInt(vars.sumSupply, comptroller.vaiMintRate());\n require(vars.mErr == MathError.NO_ERROR, \"VAI_MINT_AMOUNT_CALCULATION_FAILED\");\n\n (vars.mErr, accountMintableVAI) = divUInt(accountMintableVAI, 10000);\n require(vars.mErr == MathError.NO_ERROR, \"VAI_MINT_AMOUNT_CALCULATION_FAILED\");\n\n (vars.mErr, accountMintableVAI) = subUInt(accountMintableVAI, vars.sumBorrowPlusEffects);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.REJECTION), 0);\n }\n\n return (uint256(Error.NO_ERROR), accountMintableVAI);\n }\n\n /**\n * @notice Update treasury data\n * @param newTreasuryGuardian New Treasury Guardian address\n * @param newTreasuryAddress New Treasury Address\n * @param newTreasuryPercent New fee percentage for minting VAI that is sent to the treasury\n */\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256) {\n // Check caller is admin\n if (!(msg.sender == admin || msg.sender == treasuryGuardian)) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_TREASURY_OWNER_CHECK);\n }\n\n require(newTreasuryPercent < 1e18, \"treasury percent cap overflow\");\n\n address oldTreasuryGuardian = treasuryGuardian;\n address oldTreasuryAddress = treasuryAddress;\n uint256 oldTreasuryPercent = treasuryPercent;\n\n treasuryGuardian = newTreasuryGuardian;\n treasuryAddress = newTreasuryAddress;\n treasuryPercent = newTreasuryPercent;\n\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Gets yearly VAI interest rate based on the VAI price\n * @return uint256 Yearly VAI interest rate\n */\n function getVAIRepayRate() public view returns (uint256) {\n ResilientOracleInterface oracle = comptroller.oracle();\n MathError mErr;\n\n if (baseRateMantissa > 0) {\n if (floatRateMantissa > 0) {\n uint256 oraclePrice = oracle.getUnderlyingPrice(getVAIAddress());\n if (1e18 > oraclePrice) {\n uint256 delta;\n uint256 rate;\n\n (mErr, delta) = subUInt(1e18, oraclePrice);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, delta) = mulUInt(delta, floatRateMantissa);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, delta) = divUInt(delta, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, rate) = addUInt(delta, baseRateMantissa);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n return rate;\n } else {\n return baseRateMantissa;\n }\n } else {\n return baseRateMantissa;\n }\n } else {\n return 0;\n }\n }\n\n /**\n * @notice Get interest rate per block\n * @return uint256 Interest rate per bock\n */\n function getVAIRepayRatePerBlock() public view returns (uint256) {\n uint256 yearlyRate = getVAIRepayRate();\n\n MathError mErr;\n uint256 rate;\n\n (mErr, rate) = divUInt(yearlyRate, getBlocksPerYear());\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n return rate;\n }\n\n /**\n * @notice Get the last updated interest index for a VAI Minter\n * @param minter Address of VAI minter\n * @return uint256 Returns the interest rate index for a minter\n */\n function getVAIMinterInterestIndex(address minter) public view returns (uint256) {\n uint256 storedIndex = vaiMinterInterestIndex[minter];\n // If the user minted VAI before the stability fee was introduced, accrue\n // starting from stability fee launch\n if (storedIndex == 0) {\n return INITIAL_VAI_MINT_INDEX;\n }\n return storedIndex;\n }\n\n /**\n * @notice Get the current total VAI a user needs to repay\n * @param account The address of the VAI borrower\n * @return (uint256) The total amount of VAI the user needs to repay\n */\n function getVAIRepayAmount(address account) public view returns (uint256) {\n MathError mErr;\n uint256 delta;\n\n uint256 amount = comptroller.mintedVAIs(account);\n uint256 interest = pastVAIInterest[account];\n uint256 totalMintedVAI;\n uint256 newInterest;\n\n (mErr, totalMintedVAI) = subUInt(amount, interest);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, delta) = subUInt(vaiMintIndex, getVAIMinterInterestIndex(account));\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, newInterest) = mulUInt(delta, totalMintedVAI);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, newInterest) = divUInt(newInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, amount) = addUInt(amount, newInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n return amount;\n }\n\n /**\n * @notice Calculate how much VAI the user needs to repay\n * @param borrower The address of the VAI borrower\n * @param repayAmount The amount of VAI being returned\n * @return Amount of VAI to be burned\n * @return Amount of VAI the user needs to pay in current interest\n * @return Amount of VAI the user needs to pay in past interest\n */\n function getVAICalculateRepayAmount(\n address borrower,\n uint256 repayAmount\n ) public view returns (uint256, uint256, uint256) {\n MathError mErr;\n uint256 totalRepayAmount = getVAIRepayAmount(borrower);\n uint256 currentInterest;\n\n (mErr, currentInterest) = subUInt(totalRepayAmount, comptroller.mintedVAIs(borrower));\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, currentInterest) = addUInt(pastVAIInterest[borrower], currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n uint256 burn;\n uint256 partOfCurrentInterest = currentInterest;\n uint256 partOfPastInterest = pastVAIInterest[borrower];\n\n if (repayAmount >= totalRepayAmount) {\n (mErr, burn) = subUInt(totalRepayAmount, currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n } else {\n uint256 delta;\n\n (mErr, delta) = mulUInt(repayAmount, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_PART_CALCULATION_FAILED\");\n\n (mErr, delta) = divUInt(delta, totalRepayAmount);\n require(mErr == MathError.NO_ERROR, \"VAI_PART_CALCULATION_FAILED\");\n\n uint256 totalMintedAmount;\n (mErr, totalMintedAmount) = subUInt(totalRepayAmount, currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_MINTED_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, burn) = mulUInt(totalMintedAmount, delta);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, burn) = divUInt(burn, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfCurrentInterest) = mulUInt(currentInterest, delta);\n require(mErr == MathError.NO_ERROR, \"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfCurrentInterest) = divUInt(partOfCurrentInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfPastInterest) = mulUInt(pastVAIInterest[borrower], delta);\n require(mErr == MathError.NO_ERROR, \"VAI_PAST_INTEREST_CALCULATION_FAILED\");\n\n (mErr, partOfPastInterest) = divUInt(partOfPastInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_PAST_INTEREST_CALCULATION_FAILED\");\n }\n\n return (burn, partOfCurrentInterest, partOfPastInterest);\n }\n\n /**\n * @notice Accrue interest on outstanding minted VAI\n */\n function accrueVAIInterest() public {\n MathError mErr;\n uint256 delta;\n\n (mErr, delta) = mulUInt(getVAIRepayRatePerBlock(), getBlockNumber() - accrualBlockNumber);\n require(mErr == MathError.NO_ERROR, \"VAI_INTEREST_ACCRUE_FAILED\");\n\n (mErr, delta) = addUInt(delta, vaiMintIndex);\n require(mErr == MathError.NO_ERROR, \"VAI_INTEREST_ACCRUE_FAILED\");\n\n vaiMintIndex = delta;\n accrualBlockNumber = getBlockNumber();\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlAddress New address for the access control\n */\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\n _ensureNonzeroAddress(newAccessControlAddress);\n\n address oldAccessControlAddress = accessControl;\n accessControl = newAccessControlAddress;\n emit NewAccessControl(oldAccessControlAddress, accessControl);\n }\n\n /**\n * @notice Set VAI borrow base rate\n * @param newBaseRateMantissa the base rate multiplied by 10**18\n */\n function setBaseRate(uint256 newBaseRateMantissa) external {\n _ensureAllowed(\"setBaseRate(uint256)\");\n\n uint256 old = baseRateMantissa;\n baseRateMantissa = newBaseRateMantissa;\n emit NewVAIBaseRate(old, baseRateMantissa);\n }\n\n /**\n * @notice Set VAI borrow float rate\n * @param newFloatRateMantissa the VAI float rate multiplied by 10**18\n */\n function setFloatRate(uint256 newFloatRateMantissa) external {\n _ensureAllowed(\"setFloatRate(uint256)\");\n\n uint256 old = floatRateMantissa;\n floatRateMantissa = newFloatRateMantissa;\n emit NewVAIFloatRate(old, floatRateMantissa);\n }\n\n /**\n * @notice Set VAI stability fee receiver address\n * @param newReceiver the address of the VAI fee receiver\n */\n function setReceiver(address newReceiver) external onlyAdmin {\n _ensureNonzeroAddress(newReceiver);\n\n address old = receiver;\n receiver = newReceiver;\n emit NewVAIReceiver(old, newReceiver);\n }\n\n /**\n * @notice Set VAI mint cap\n * @param _mintCap the amount of VAI that can be minted\n */\n function setMintCap(uint256 _mintCap) external {\n _ensureAllowed(\"setMintCap(uint256)\");\n\n uint256 old = mintCap;\n mintCap = _mintCap;\n emit NewVAIMintCap(old, _mintCap);\n }\n\n function getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n function getBlocksPerYear() public view virtual returns (uint256) {\n return 70080000; //(24 * 60 * 60 * 365) / 0.45;\n }\n\n /**\n * @notice Return the address of the VAI token\n * @return The address of VAI\n */\n function getVAIAddress() public view virtual returns (address) {\n return vai;\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin can\");\n _;\n }\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n function _ensureAllowed(string memory functionSig) private view {\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \"access denied\");\n }\n\n /// @dev Reverts if the protocol is paused\n function _ensureNotPaused() private view {\n require(!comptroller.protocolPaused(), \"protocol is paused\");\n }\n\n /// @dev Reverts if the passed address is zero\n function _ensureNonzeroAddress(address someone) private pure {\n require(someone != address(0), \"can't be zero address\");\n }\n\n /// @dev Reverts if the passed amount is zero\n function _ensureNonzeroAmount(uint256 amount) private pure {\n require(amount > 0, \"amount can't be zero\");\n }\n\n /// @dev Persists the DBO protection window for every market the minter has entered, so VAI minting\n /// records the same on-chain price history as the borrow path. Extracted from `mintVAI` to avoid\n /// stack-too-deep in that function.\n function _updateProtectionStateForEnteredMarkets(address minter) private {\n IDeviationBoundedOracle dbo = comptroller.deviationBoundedOracle();\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\n uint256 enteredLength = enteredMarkets.length;\n for (uint256 i; i < enteredLength; ++i) {\n dbo.updateProtectionState(address(enteredMarkets[i]));\n }\n }\n}\n" + }, + "contracts/Tokens/VAI/VAIControllerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VTokenInterface } from \"../VTokens/VTokenInterfaces.sol\";\n\ninterface VAIControllerInterface {\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\n\n function repayVAI(uint256 amount) external returns (uint256, uint256);\n\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\n\n function liquidateVAI(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint256, uint256);\n\n function getMintableVAI(address minter) external view returns (uint256, uint256);\n\n function getVAIAddress() external view returns (address);\n\n function getVAIRepayAmount(address account) external view returns (uint256);\n}\n" + }, + "contracts/Tokens/VAI/VAIControllerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\n\ncontract VAIUnitrollerAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of Unitroller\n */\n address public vaiControllerImplementation;\n\n /**\n * @notice Pending brains of Unitroller\n */\n address public pendingVAIControllerImplementation;\n}\n\ncontract VAIControllerStorageG1 is VAIUnitrollerAdminStorage {\n ComptrollerInterface public comptroller;\n\n struct VenusVAIState {\n /// @notice The last updated venusVAIMintIndex\n uint224 index;\n /// @notice The block number the index was last updated at\n uint32 block;\n }\n\n /// @notice The Venus VAI state\n VenusVAIState public venusVAIState;\n\n /// @notice The Venus VAI state initialized\n bool public isVenusVAIInitialized;\n\n /// @notice The Venus VAI minter index as of the last time they accrued XVS\n mapping(address => uint256) public venusVAIMinterIndex;\n}\n\ncontract VAIControllerStorageG2 is VAIControllerStorageG1 {\n /// @notice Treasury Guardian address\n address public treasuryGuardian;\n\n /// @notice Treasury address\n address public treasuryAddress;\n\n /// @notice Fee percent of accrued interest with decimal 18\n uint256 public treasuryPercent;\n\n /// @notice Guard variable for re-entrancy checks\n bool internal _notEntered;\n\n /// @notice The base rate for stability fee\n uint256 public baseRateMantissa;\n\n /// @notice The float rate for stability fee\n uint256 public floatRateMantissa;\n\n /// @notice The address for VAI interest receiver\n address public receiver;\n\n /// @notice Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\n uint256 public vaiMintIndex;\n\n /// @notice Block number that interest was last accrued at\n uint256 internal accrualBlockNumber;\n\n /// @notice Global vaiMintIndex as of the most recent balance-changing action for user\n mapping(address => uint256) internal vaiMinterInterestIndex;\n\n /// @notice Tracks the amount of mintedVAI of a user that represents the accrued interest\n mapping(address => uint256) public pastVAIInterest;\n\n /// @notice VAI mint cap\n uint256 public mintCap;\n\n /// @notice Access control manager address\n address public accessControl;\n}\n\ncontract VAIControllerStorageG3 is VAIControllerStorageG2 {\n /// @notice The address of the prime contract. It can be a ZERO address\n address public prime;\n\n /// @notice Tracks if minting is enabled only for prime token holders. Only used if prime is set\n bool public mintEnabledOnlyForPrimeHolder;\n}\n\ncontract VAIControllerStorageG4 is VAIControllerStorageG3 {\n /// @notice The address of the VAI token\n address internal vai;\n}\n" + }, + "contracts/Tokens/VAI/VAIUnitroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { VAIControllerErrorReporter } from \"../../Utils/ErrorReporter.sol\";\nimport { VAIUnitrollerAdminStorage } from \"./VAIControllerStorage.sol\";\n\n/**\n * @title VAI Unitroller\n * @author Venus\n * @notice This is the proxy contract for the VAIComptroller\n */\ncontract VAIUnitroller is VAIUnitrollerAdminStorage, VAIControllerErrorReporter {\n /**\n * @notice Emitted when pendingVAIControllerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingVAIControllerImplementation is accepted, which means comptroller implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor() {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public returns (uint256) {\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation = pendingVAIControllerImplementation;\n\n pendingVAIControllerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public returns (uint256) {\n // Check caller is pendingImplementation\n if (msg.sender != pendingVAIControllerImplementation) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldImplementation = vaiControllerImplementation;\n address oldPendingImplementation = pendingVAIControllerImplementation;\n\n vaiControllerImplementation = pendingVAIControllerImplementation;\n\n pendingVAIControllerImplementation = address(0);\n\n emit NewImplementation(oldImplementation, vaiControllerImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public returns (uint256) {\n // Check caller = admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n }\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public returns (uint256) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n fallback() external {\n // delegate all other functions to current implementation\n (bool success, ) = vaiControllerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VBep20Interface, VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { VToken } from \"./VToken.sol\";\n\n/**\n * @title Venus's VBep20 Contract\n * @notice vTokens which wrap an ERC-20 underlying\n * @author Venus\n */\ncontract VBep20 is VToken, VBep20Interface {\n using SafeERC20 for IERC20;\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits Mint event\n function mint(uint mintAmount) external returns (uint) {\n (uint err, ) = mintInternal(mintAmount);\n return err;\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver The account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits MintBehalf event\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n (uint err, ) = mintBehalfInternal(receiver, mintAmount);\n return err;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemer The user on behalf of whom to redeem\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemBehalf(address redeemer, uint redeemTokens) external returns (uint) {\n require(comptroller.approvedDelegates(redeemer, msg.sender), \"not an approved delegate\");\n\n return redeemInternal(redeemer, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemer, on behalf of whom to redeem\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlyingBehalf(address redeemer, uint redeemAmount) external returns (uint) {\n require(comptroller.approvedDelegates(redeemer, msg.sender), \"not an approved delegate\");\n\n return redeemUnderlyingInternal(redeemer, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender borrows assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the borrower using `comptroller.updateDelegate`\n * @param borrower The borrower, on behalf of whom to borrow.\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrowBehalf(address borrower, uint borrowAmount) external returns (uint) {\n require(comptroller.approvedDelegates(borrower, msg.sender), \"not an approved delegate\");\n return borrowInternal(borrower, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrow(uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrowing account\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\n return err;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emit LiquidateBorrow event on success\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n (uint err, ) = liquidateBorrowInternal(borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying tokens to add as reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesAdded event\n function _addReserves(uint addAmount) external returns (uint) {\n return _addReservesInternal(addAmount);\n }\n\n /**\n * @notice Initialize the new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n // VToken initialize does the bulk of the work\n super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20(underlying).totalSupply();\n }\n\n /*** Safe Token ***/\n\n /**\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n * Increments `internalCash` by the actual amount received.\n * @param from Sender of the underlying tokens\n * @param amount Amount of underlying to transfer\n * @return Actual amount received\n */\n function doTransferIn(address from, uint256 amount) internal virtual override returns (uint256) {\n IERC20 token = IERC20(underlying);\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n uint256 actualAmount = balanceAfter - balanceBefore;\n internalCash += actualAmount;\n // Return the amount that was *actually* transferred\n return actualAmount;\n }\n\n /**\n * @dev Just a regular ERC-20 transfer, reverts on failure.\n * Decrements `internalCash` by `amount` before transferring.\n * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function doTransferOut(address payable to, uint256 amount) internal virtual override {\n internalCash -= amount;\n IERC20 token = IERC20(underlying);\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Gets the tracked internal cash balance of this contract\n * @dev Returns `internalCash` rather than the actual token balance, making it immune to donation attacks.\n * @return The internally tracked cash balance of underlying tokens\n */\n function getCashPrior() internal view override returns (uint) {\n return internalCash;\n }\n\n /**\n * @notice Transfer excess tokens to caller and sync internalCash with actual balance\n * @dev Admin-only. For migration: pass 0 (just syncs). For sweep: pass the excess amount.\n * Transfers `transferAmount` of underlying to msg.sender, then sets internalCash = balanceOf(address(this)).\n * @param transferAmount Amount of underlying to transfer to msg.sender before syncing\n */\n function sweepTokenAndSync(uint256 transferAmount) external {\n require(msg.sender == admin);\n\n if (transferAmount > 0) {\n IERC20(underlying).safeTransfer(msg.sender, transferAmount);\n emit TokenSwept(msg.sender, transferAmount);\n }\n\n uint256 oldInternalCash = internalCash;\n internalCash = IERC20(underlying).balanceOf(address(this));\n emit CashSynced(oldInternalCash, internalCash);\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Delegate.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VBep20 } from \"./VBep20.sol\";\nimport { VDelegateInterface } from \"./VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20Delegate Contract\n * @notice VTokens which wrap an EIP-20 underlying and are delegated to\n * @author Venus\n */\ncontract VBep20Delegate is VBep20, VDelegateInterface {\n /**\n * @notice Construct an empty delegate\n */\n constructor() {}\n\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) public {\n // Shh -- currently unused\n data;\n\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _becomeImplementation\");\n }\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() public {\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _resignImplementation\");\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Delegator.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VTokenInterface, VBep20Interface, VDelegatorInterface } from \"./VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20Delegator Contract\n * @notice vTokens which wrap an EIP-20 underlying and delegate to an implementation\n * @author Venus\n */\ncontract VBep20Delegator is VTokenInterface, VBep20Interface, VDelegatorInterface {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData The encoded args for becomeImplementation\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(\n implementation_,\n abi.encodeWithSignature(\n \"initialize(address,address,address,uint256,string,string,uint8)\",\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n )\n );\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_, false, becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n */\n fallback() external {\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function mint(uint mintAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"mint(uint256)\", mintAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"mintBehalf(address,uint256)\", receiver, mintAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying asset\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeem(uint redeemTokens) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"redeem(uint256)\", redeemTokens));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"redeemUnderlying(uint256)\", redeemAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function borrow(uint borrowAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrow(uint256)\", borrowAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function repayBorrow(uint repayAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"repayBorrow(uint256)\", repayAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrower\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"repayBorrowBehalf(address,uint256)\", borrower, repayAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"liquidateBorrow(address,uint256,address)\", borrower, repayAmount, vTokenCollateral)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"transfer(address,uint256)\", dst, amount));\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"transferFrom(address,address,uint256)\", src, dst, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"approve(address,uint256)\", spender, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"balanceOfUnderlying(address)\", owner));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"totalBorrowsCurrent()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrowBalanceCurrent(address)\", account));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function seize(address liquidator, address borrower, uint seizeTokens) external override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"seize(address,address,uint256)\", liquidator, borrower, seizeTokens)\n );\n return abi.decode(data, (uint));\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setPendingAdmin(address)\", newPendingAdmin)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setReserveFactor(uint newReserveFactorMantissa) external override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setReserveFactor(uint256)\", newReserveFactorMantissa)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accepts transfer of admin rights. `msg.sender` must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _acceptAdmin() external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_acceptAdmin()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from admin\n * @param addAmount Amount of reserves to add\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _addReserves(uint addAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_addReserves(uint256)\", addAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReserves(uint reduceAmount) external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_reduceReserves(uint256)\", reduceAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"getCash()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"allowance(address,address)\", owner, spender)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"balanceOf(address)\", owner));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get a snapshot of the account's balances and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"getAccountSnapshot(address)\", account)\n );\n return abi.decode(data, (uint, uint, uint, uint));\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"borrowRatePerBlock()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"supplyRatePerBlock()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n // @custom:access Only callable by admin\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) public {\n require(msg.sender == admin, \"VBep20Delegator::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature(\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"exchangeRateCurrent()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves.\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n function accrueInterest() public override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"accrueInterest()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setComptroller(address)\", newComptroller)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using `_setInterestRateModelFresh`\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel The new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setInterestRateModel(address)\", newInterestRateModel)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Delegates execution to the implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToImplementation(bytes memory data) public returns (bytes memory) {\n return delegateTo(implementation, data);\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n (bool success, bytes memory returnData) = address(this).staticcall(\n abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data)\n );\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize())\n }\n }\n return abi.decode(returnData, (bytes));\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view override returns (uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"borrowBalanceStored(address)\", account)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() public view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"exchangeRateStored()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize())\n }\n }\n return returnData;\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Immutable.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VBep20 } from \"./VBep20.sol\";\n\n/**\n * @title Venus's VBep20Immutable Contract\n * @notice VTokens which wrap an EIP-20 underlying and are immutable\n * @author Venus\n */\ncontract VBep20Immutable is VBep20 {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n // Initialize the market\n initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n );\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBNB.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VToken } from \"./VToken.sol\";\n\n/**\n * @title Venus's vBNB Contract\n * @notice vToken which wraps BNB\n * @author Venus\n */\ncontract VBNB is VToken {\n /**\n * @notice Construct a new vBNB money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n */\n constructor(\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Send BNB to VBNB to mint\n */\n receive() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Reverts upon any failure\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits Mint event\n function mint() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @dev Reverts upon any failure\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrow() external payable {\n (uint err, ) = repayBorrowInternal(msg.value);\n requireNoError(err, \"repayBorrow failed\");\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @dev Reverts upon any failure\n * @param borrower The account with the debt being payed off\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrowBehalf(address borrower) external payable {\n (uint err, ) = repayBorrowBehalfInternal(borrower, msg.value);\n requireNoError(err, \"repayBorrowBehalf failed\");\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @dev Reverts upon any failure\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n */\n // @custom:event Emit LiquidateBorrow event on success\n function liquidateBorrow(address borrower, VToken vTokenCollateral) external payable {\n (uint err, ) = liquidateBorrowInternal(borrower, msg.value, vTokenCollateral);\n requireNoError(err, \"liquidateBorrow failed\");\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Perform the actual transfer in, which is a no-op\n * @param from Address sending the BNB\n * @param amount Amount of BNB being sent\n * @return The actual amount of BNB transferred\n */\n function doTransferIn(address from, uint amount) internal override returns (uint) {\n // Sanity checks\n require(msg.sender == from, \"sender mismatch\");\n require(msg.value == amount, \"value mismatch\");\n return amount;\n }\n\n function doTransferOut(address payable to, uint amount) internal override {\n /* Send the BNB, with minimal gas and revert on failure */\n to.transfer(amount);\n }\n\n /**\n * @notice Gets balance of this contract in terms of BNB, before this message\n * @dev This excludes the value of the current message, if any\n * @return The quantity of BNB owned by this contract\n */\n function getCashPrior() internal view override returns (uint) {\n (MathError err, uint startingBalance) = subUInt(address(this).balance, msg.value);\n require(err == MathError.NO_ERROR, \"cash prior math error\");\n return startingBalance;\n }\n\n function requireNoError(uint errCode, string memory message) internal pure {\n if (errCode == uint(Error.NO_ERROR)) {\n return;\n }\n\n bytes memory fullMessage = new bytes(bytes(message).length + 5);\n uint i;\n\n for (i = 0; i < bytes(message).length; i++) {\n fullMessage[i] = bytes(message)[i];\n }\n\n fullMessage[i + 0] = bytes1(uint8(32));\n fullMessage[i + 1] = bytes1(uint8(40));\n fullMessage[i + 2] = bytes1(uint8(48 + (errCode / 10)));\n fullMessage[i + 3] = bytes1(uint8(48 + (errCode % 10)));\n fullMessage[i + 4] = bytes1(uint8(41));\n\n require(errCode == uint(Error.NO_ERROR), string(fullMessage));\n }\n}\n" + }, + "contracts/Tokens/VTokens/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\nimport { IProtocolShareReserve } from \"../../external/IProtocolShareReserve.sol\";\nimport { ComptrollerInterface, IComptroller } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"../../Utils/ErrorReporter.sol\";\nimport { Exponential } from \"../../Utils/Exponential.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { MANTISSA_ONE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\n/**\n * @title Venus's vToken Contract\n * @notice Abstract base for vTokens\n * @author Venus\n */\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\n struct MintLocalVars {\n MathError mathErr;\n uint exchangeRateMantissa;\n uint mintTokens;\n uint totalSupplyNew;\n uint accountTokensNew;\n uint actualMintAmount;\n }\n\n struct RedeemLocalVars {\n MathError mathErr;\n uint exchangeRateMantissa;\n uint redeemTokens;\n uint redeemAmount;\n uint totalSupplyNew;\n uint accountTokensNew;\n }\n\n struct BorrowLocalVars {\n MathError mathErr;\n uint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n }\n\n struct RepayBorrowLocalVars {\n Error err;\n MathError mathErr;\n uint repayAmount;\n uint borrowerIndex;\n uint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n uint actualRepayAmount;\n }\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n // @custom:event Emits Transfer event\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n // @custom:event Emits Transfer event\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\n * @return Whether or not the approval succeeded\n */\n // @custom:event Emits Approval event on successful approve\n function approve(address spender, uint256 amount) external override returns (bool) {\n transferAllowances[msg.sender][spender] = amount;\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\n ensureNoMathError(mErr);\n return balance;\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return totalBorrows;\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return borrowBalanceStored(account);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n function seize(\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external override nonReentrant returns (uint) {\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\n // Check caller = admin\n ensureAdmin(msg.sender);\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewAdmin event on successful acceptance\n // @custom:event Emits NewPendingAdmin event with null new pending admin\n function _acceptAdmin() external override returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = payable(address(0));\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\n * @dev Governor function to accrue interest and set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewReserveFactor event\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\n ensureAllowed(\"_setReserveFactor(uint256)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\n }\n\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\n return _setReserveFactorFresh(newReserveFactorMantissa_);\n }\n\n /**\n * @notice Sets the address of the access control manager of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlManagerAddress New address for the access control\n * @return uint 0=success, otherwise will revert\n */\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\n // Check caller is admin\n ensureAdmin(msg.sender);\n\n ensureNonZeroAddress(newAccessControlManagerAddress);\n\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\n accessControlManager = newAccessControlManagerAddress;\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\n * @param reduceAmount_ Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesReduced event\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\n ensureAllowed(\"_reduceReserves(uint256)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n\n // If reserves were reduced in accrueInterest\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\n return _reduceReservesFresh(reduceAmount_);\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n return transferAllowances[owner][spender];\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n return accountTokens[owner];\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\n uint borrowBalance;\n uint exchangeRateMantissa;\n\n MathError mErr;\n\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0, 0);\n }\n\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0, 0);\n }\n\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint) {\n return\n interestRateModel.getSupplyRate(\n _getCashPriorWithFlashLoan(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa\n );\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint) {\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint) {\n return getCashPrior();\n }\n\n /**\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\n * @param newReduceReservesBlockDelta_ block difference value\n */\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\n require(newReduceReservesBlockDelta_ > 0, \"Invalid Input\");\n ensureAllowed(\"setReduceReservesBlockDelta(uint256)\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protcolShareReserve_ The address of protocol share reserve contract\n */\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\n // Check caller is admin\n ensureAdmin(msg.sender);\n ensureNonZeroAddress(protcolShareReserve_);\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\n protocolShareReserve = protcolShareReserve_;\n }\n\n /**\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\n * asset by calling the `doTransferOut` internal function.\n * - The caller must be the Comptroller contract.\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\n * @param to The address to which the underlying asset is to be transferred.\n * @param amount The amount of the underlying asset to transfer.\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\n */\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\n if (msg.sender != address(comptroller)) {\n revert InvalidComptroller();\n }\n\n if (flashLoanAmount > 0) {\n revert FlashLoanAlreadyActive();\n }\n\n if (getCashPrior() < amount) {\n revert InsufficientCash();\n }\n flashLoanAmount = amount;\n doTransferOut(to, amount);\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\n }\n\n /**\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\n * - The caller must be the Comptroller contract.\n * - Transfers the protocol fee to the protocol share reserve.\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\n * @param from The address from which the underlying asset is to be transferred.\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\n * @param totalFee The total fee amount for the flash loan.\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\n */\n function transferInUnderlyingFlashLoan(\n address payable from,\n uint256 repaymentAmount,\n uint256 totalFee,\n uint256 protocolFee\n ) external nonReentrant returns (uint256) {\n if (msg.sender != address(comptroller)) {\n revert InvalidComptroller();\n }\n\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\n\n if (actualAmountTransferred < totalFee) {\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\n }\n\n // Transfer protocol fee to protocol share reserve\n doTransferOut(protocolShareReserve, protocolFee);\n\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.FLASHLOAN\n );\n\n // Reset flashLoanAmount to complete the flash loan cycle\n flashLoanAmount = 0;\n\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\n return actualAmountTransferred;\n }\n\n /**\n * @notice Sets flash loan status for the market\n * @param enabled True to enable flash loans, false to disable\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n * @custom:access Only Governance\n * @custom:event Emits FlashLoanStatusChanged event on success\n */\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\n ensureAllowed(\"setFlashLoanEnabled(bool)\");\n\n if (isFlashLoanEnabled != enabled) {\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\n isFlashLoanEnabled = enabled;\n }\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Update flashLoan fee mantissa\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n * @custom:access Only Governance\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\n * @custom:event Emits FlashLoanFeeUpdated event on success\n */\n function setFlashLoanFeeMantissa(\n uint256 flashLoanFeeMantissa_,\n uint256 flashLoanProtocolShare_\n ) external returns (uint256) {\n ensureAllowed(\"setFlashLoanFeeMantissa(uint256,uint256)\");\n\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\n }\n\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\n }\n\n // Only proceed if values are changing\n if (\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\n ) {\n emit FlashLoanFeeUpdated(\n flashLoanFeeMantissa,\n flashLoanFeeMantissa_,\n flashLoanProtocolShareMantissa,\n flashLoanProtocolShare_\n );\n\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\n }\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Initialize the money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ EIP-20 name of this token\n * @param symbol_ EIP-20 symbol of this token\n * @param decimals_ EIP-20 decimal precision of this token\n */\n function initialize(\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n ensureAdmin(msg.sender);\n require(accrualBlockNumber == 0 && borrowIndex == 0, \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa > 0, \"initial exchange rate must be greater than zero.\");\n\n // Set the comptroller\n uint err = _setComptroller(comptroller_);\n require(err == uint(Error.NO_ERROR), \"setting comptroller failed\");\n\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n accrualBlockNumber = block.number;\n borrowIndex = mantissaOne;\n\n // Set the interest rate model (depends on block number / borrow index)\n err = _setInterestRateModelFresh(interestRateModel_);\n require(err == uint(Error.NO_ERROR), \"setting interest rate model failed\");\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return exchangeRateStored();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\n */\n // @custom:event Emits AccrueInterest event\n function accrueInterest() public virtual override returns (uint) {\n /* Remember the initial block number */\n uint currentBlockNumber = block.number;\n uint accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return uint(Error.NO_ERROR);\n }\n\n /* Read the previous values out of storage */\n uint cashPrior = _getCashPriorWithFlashLoan();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\n uint borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n require(borrowRateMantissa <= borrowRateMaxMantissa, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n ensureNoMathError(mathErr);\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor;\n uint interestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\n ensureNoMathError(mathErr);\n if (blockDelta >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentBlockNumber;\n uint actualCash = getCashPrior();\n if (actualCash < totalReservesNew) {\n _reduceReservesFresh(actualCash);\n } else {\n _reduceReservesFresh(totalReservesNew);\n }\n }\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewComptroller event\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\n // Check caller is admin\n ensureAdmin(msg.sender);\n\n // Ensure invoke comptroller.isComptroller() returns true\n require(newComptroller.isComptroller(), \"marker method returned false\");\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(comptroller, newComptroller);\n\n // Set market's comptroller to newComptroller\n comptroller = newComptroller;\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Governance function to accrue interest and update the interest rate model\n * @param newInterestRateModel_ The new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\n ensureAllowed(\"_setInterestRateModel(address)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\n }\n\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\n return _setInterestRateModelFresh(newInterestRateModel_);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() public view override returns (uint) {\n (MathError err, uint result) = exchangeRateStoredInternal();\n ensureNoMathError(err);\n return result;\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view override returns (uint) {\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\n ensureNoMathError(err);\n return result;\n }\n\n /**\n * @notice Opens a debt position for the borrower as part of flash loan repayment\n * @dev This function is specifically called during flash loan operations when the repayment\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\n * and updates the borrower's balance. It also emits a Borrow event and calls the\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\n * if the market's block number is not current.\n * @param borrower The address of the borrower who will have the debt position created\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\n */\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\n // Reverts if the caller is not the comptroller\n if (msg.sender != address(comptroller)) {\n revert InvalidComptroller();\n }\n\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors.\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\n }\n\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\n }\n\n /**\n * @notice Calculates the total fee and protocol fee for a flash loan..\n * @param amount The amount of the flash loan.\n * @return totalFee The total fee for the flash loan.\n * @return protocolFee The portion of the total fee allocated to the protocol.\n */\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\n MathError mErr;\n uint256 totalFee;\n uint256 protocolFee;\n\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\n ensureNoMathError(mErr);\n\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\n ensureNoMathError(mErr);\n\n return (totalFee, protocolFee);\n }\n\n /**\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\n * @dev Called by both `transfer` and `transferFrom` internally\n * @param spender The address of the account performing the transfer\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param tokens The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\n /* Fail if transfer not allowed */\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\n if (allowed != 0) {\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Do not allow self-transfers */\n if (src == dst) {\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n /* Get the allowance, infinite for the account owner */\n uint startingAllowance = 0;\n if (spender == src) {\n startingAllowance = type(uint256).max;\n } else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under,over}flow */\n MathError mathErr;\n uint allowanceNew;\n uint srvTokensNew;\n uint dstTokensNew;\n\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\n }\n\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n accountTokens[src] = srvTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if necessary) */\n if (startingAllowance != type(uint256).max) {\n transferAllowances[src][spender] = allowanceNew;\n }\n\n /* We emit a Transfer event */\n emit Transfer(src, dst, tokens);\n\n comptroller.transferVerify(address(this), src, dst, tokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\n }\n\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n return mintFresh(msg.sender, mintAmount);\n }\n\n /**\n * @notice User supplies assets into the market and receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param minter The address of the account which is supplying the assets\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\n /* Fail if mint not allowed */\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\n }\n\n MintLocalVars memory vars;\n\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the minter and the mintAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\n vars.actualMintAmount,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n /*\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[minter] = vars.accountTokensNew;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\n emit Transfer(address(this), minter, vars.mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\n\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver The address of the account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\n }\n\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\n }\n\n /**\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param payer The address of the account which is paying the underlying token\n * @param receiver The address of the account which is receiving vToken\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\n ensureNonZeroAddress(receiver);\n /* Fail if mint not allowed */\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\n }\n\n MintLocalVars memory vars;\n\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the payer and the mintAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\n vars.actualMintAmount,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n /*\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[receiver] + mintTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[receiver] = vars.accountTokensNew;\n\n /* We emit a MintBehalf event, and a Transfer event */\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\n emit Transfer(address(this), receiver, vars.mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\n\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the tokens\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemInternal(\n address redeemer,\n address payable receiver,\n uint redeemTokens\n ) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\n }\n\n /**\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemUnderlyingInternal(\n address redeemer,\n address payable receiver,\n uint redeemAmount\n ) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\n }\n\n /**\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the tokens\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // solhint-disable-next-line code-complexity\n function redeemFresh(\n address redeemer,\n address payable receiver,\n uint redeemTokensIn,\n uint redeemAmountIn\n ) internal returns (uint) {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n RedeemLocalVars memory vars;\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n ensureNoMathError(vars.mathErr);\n\n /* If redeemTokensIn > 0: */\n if (redeemTokensIn > 0) {\n /*\n * We calculate the exchange rate and the amount of underlying to be redeemed:\n * redeemTokens = redeemTokensIn\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\n */\n vars.redeemTokens = redeemTokensIn;\n\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\n Exp({ mantissa: vars.exchangeRateMantissa }),\n redeemTokensIn\n );\n ensureNoMathError(vars.mathErr);\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n * redeemAmount = redeemAmountIn\n */\n\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\n redeemAmountIn,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n vars.redeemAmount = redeemAmountIn;\n }\n\n /* Fail if redeem not allowed */\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\n if (allowed != 0) {\n revert(\"math error\");\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n revert(\"math error\");\n }\n\n /*\n * We calculate the new total supply and redeemer balance, checking for underflow:\n * totalSupplyNew = totalSupply - redeemTokens\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\n ensureNoMathError(vars.mathErr);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (getCashPrior() < vars.redeemAmount) {\n revert(\"math error\");\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[redeemer] = vars.accountTokensNew;\n\n /*\n * We invoke doTransferOut for the receiver and the redeemAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken has redeemAmount less of cash.\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n\n uint feeAmount;\n uint remainedAmount;\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\n (vars.mathErr, feeAmount) = mulUInt(\n vars.redeemAmount,\n IComptroller(address(comptroller)).treasuryPercent()\n );\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\n ensureNoMathError(vars.mathErr);\n\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\n doTransferOut(treasuryAddress, feeAmount);\n\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\n } else {\n remainedAmount = vars.redeemAmount;\n }\n\n doTransferOut(receiver, remainedAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), vars.redeemTokens);\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Receiver gets the borrow on behalf of the borrower address\n * @param borrower The borrower, on behalf of whom to borrow\n * @param receiver The account that would receive the funds (can be the same as the borrower)\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function borrowInternal(\n address borrower,\n address payable receiver,\n uint borrowAmount\n ) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\n }\n\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n return borrowFresh(borrower, receiver, borrowAmount, true);\n }\n\n /**\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\n * @dev Before calling this function, ensure that the interest has been accrued\n * @param borrower The borrower, on behalf of whom to borrow\n * @param receiver The account that would receive the funds (can be the same as the borrower)\n * @param borrowAmount The amount of the underlying asset to borrow\n * @param shouldTransfer Whether to call doTransferOut for the receiver\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\n */\n function borrowFresh(\n address borrower,\n address payable receiver,\n uint borrowAmount,\n bool shouldTransfer\n ) internal returns (uint) {\n /* Revert if borrow not allowed */\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\n\n if (allowed != 0) {\n revert(\"math error\");\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n revert(\"math error\");\n }\n\n /* Revert if protocol has insufficient underlying cash */\n if (shouldTransfer && getCashPrior() < borrowAmount) {\n revert(\"math error\");\n }\n\n BorrowLocalVars memory vars;\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowsNew = accountBorrows + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\n ensureNoMathError(vars.mathErr);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n if (shouldTransfer) {\n /*\n * We invoke doTransferOut for the receiver and the borrowAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken borrowAmount less of cash.\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n doTransferOut(receiver, borrowAmount);\n }\n\n /* We emit a Borrow event */\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\n }\n\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrowing account\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\n }\n\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\n }\n\n /**\n * @notice Borrows are repaid by another user (possibly the borrower).\n * @param payer The account paying off the borrow\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount of undelrying tokens being returned\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\n /* Fail if repayBorrow not allowed */\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\n if (allowed != 0) {\n return (\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\n 0\n );\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\n }\n\n RepayBorrowLocalVars memory vars;\n\n /* We remember the original borrowerIndex for verification purposes */\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n if (vars.mathErr != MathError.NO_ERROR) {\n return (\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n uint(vars.mathErr)\n ),\n 0\n );\n }\n\n // caps the repayAmount to the actual owed amount\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call doTransferIn for the payer and the repayAmount\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken holds an additional repayAmount of cash.\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\n\n /*\n * We calculate the new borrower and total borrow balances, failing on underflow:\n * accountBorrowsNew = accountBorrows - actualRepayAmount\n * totalBorrowsNew = totalBorrows - actualRepayAmount\n */\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\n ensureNoMathError(vars.mathErr);\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\n\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function liquidateBorrowInternal(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\n }\n\n error = vTokenCollateral.accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\n }\n\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n // solhint-disable-next-line code-complexity\n function liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) internal returns (uint, uint) {\n /* Fail if liquidate not allowed */\n uint allowed = comptroller.liquidateBorrowAllowed(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n repayAmount\n );\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n /* Fail if repayBorrow fails */\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\n if (repayBorrowError != uint(Error.NO_ERROR)) {\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\n borrower,\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n\n require(amountSeizeError == uint(Error.NO_ERROR), \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"LIQUIDATE_SEIZE_TOO_MUCH\");\n\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\n uint seizeError;\n if (address(vTokenCollateral) == address(this)) {\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\n } else {\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\n require(seizeError == uint(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.liquidateBorrowVerify(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n actualRepayAmount,\n seizeTokens\n );\n\n return (uint(Error.NO_ERROR), actualRepayAmount);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function seizeInternal(\n address seizerToken,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) internal returns (uint) {\n /* Fail if seize not allowed */\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\n if (allowed != 0) {\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\n }\n\n MathError mathErr;\n uint borrowerTokensNew;\n uint liquidatorTokensNew;\n\n /*\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\n */\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\n if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\n }\n\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\n if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accountTokens[borrower] = borrowerTokensNew;\n accountTokens[liquidator] = liquidatorTokensNew;\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, seizeTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\n * @dev Governance function to set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\n // Verify market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\n }\n\n uint oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\n * @param addAmount Amount of addition to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\n (error, ) = _addReservesFresh(addAmount);\n return error;\n }\n\n /**\n * @notice Add reserves by transferring from caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\n */\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\n // totalReserves + actualAddAmount\n uint totalReservesNew;\n uint actualAddAmount;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call doTransferIn for the caller and the addAmount\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken holds an additional addAmount of cash.\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n\n actualAddAmount = doTransferIn(msg.sender, addAmount);\n\n totalReservesNew = totalReserves + actualAddAmount;\n\n /* Revert on overflow */\n require(totalReservesNew >= totalReserves, \"add reserves unexpected overflow\");\n\n // Store reserves[n+1] = reserves[n] + actualAddAmount\n totalReserves = totalReservesNew;\n\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n /* Return (NO_ERROR, actualAddAmount) */\n return (uint(Error.NO_ERROR), actualAddAmount);\n }\n\n /**\n * @notice Reduces reserves by transferring to protocol share reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\n if (reduceAmount == 0) {\n return uint(Error.NO_ERROR);\n }\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (getCashPrior() < reduceAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReserves - reduceAmount;\n\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n doTransferOut(protocolShareReserve, reduceAmount);\n\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice updates the interest rate model (requires fresh interest accrual)\n * @dev Governance function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\n }\n\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n require(newInterestRateModel.isInterestRateModel(), \"marker method returned false\");\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\n\n // Set the interest rate model to newInterestRateModel\n interestRateModel = newInterestRateModel;\n\n return uint(Error.NO_ERROR);\n }\n\n /*** Safe Token ***/\n\n /**\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\n * This may revert due to insufficient balance or insufficient allowance.\n */\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\n\n /**\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\n */\n function doTransferOut(address payable to, uint amount) internal virtual;\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\n */\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\n /* Note: we do not assert that the market is up to date */\n MathError mathErr;\n uint principalTimesIndex;\n uint result;\n\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\n\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n */\n if (borrowSnapshot.principal == 0) {\n return (MathError.NO_ERROR, 0);\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n return (MathError.NO_ERROR, result);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the vToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\n */\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\n uint _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\n } else {\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\n */\n uint totalCash = _getCashPriorWithFlashLoan();\n uint cashPlusBorrowsMinusReserves;\n Exp memory exchangeRate;\n MathError mathErr;\n\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n return (MathError.NO_ERROR, exchangeRate.mantissa);\n }\n }\n\n /**\n * @notice Gets balance of this contract including active flash loans\n * @return The quantity of underlying owned by this contract plus active flash loan amount\n */\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\n return getCashPrior() + flashLoanAmount;\n }\n\n function ensureAllowed(string memory functionSig) private view {\n require(\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\n \"access denied\"\n );\n }\n\n function ensureAdmin(address caller_) private view {\n require(caller_ == admin, \"Unauthorized\");\n }\n\n function ensureNoMathError(MathError mErr) private pure {\n require(mErr == MathError.NO_ERROR, \"math error\");\n }\n\n function ensureNonZeroAddress(address address_) private pure {\n require(address_ != address(0), \"zero address\");\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying owned by this contract\n */\n function getCashPrior() internal view virtual returns (uint);\n}\n" + }, + "contracts/Tokens/VTokens/VTokenInterfaces.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\n\ncontract VTokenStorageBase {\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\n */\n struct BorrowSnapshot {\n uint principal;\n uint interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice EIP-20 token name for this token\n */\n string public name;\n\n /**\n * @notice EIP-20 token symbol for this token\n */\n string public symbol;\n\n /**\n * @notice EIP-20 token decimals for this token\n */\n uint8 public decimals;\n\n /**\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\n */\n\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice Maximum fraction of interest that can be set aside for reserves\n */\n uint internal constant reserveFactorMaxMantissa = 1e18;\n\n /**\n * @notice Administrator for this contract\n */\n address payable public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address payable public pendingAdmin;\n\n /**\n * @notice Contract which oversees inter-vToken operations\n */\n ComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\n InterestRateModelV8 public interestRateModel;\n\n /**\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n uint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @notice Official record of token balances for each account\n */\n mapping(address => uint) internal accountTokens;\n\n /**\n * @notice Approved token transfer amounts on behalf of others\n */\n mapping(address => mapping(address => uint)) internal transferAllowances;\n\n /**\n * @notice Mapping of account addresses to outstanding borrow balances\n */\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\n\n /**\n * @notice Implementation address for this contract\n */\n address public implementation;\n\n /**\n * @notice delta block after which reserves will be reduced\n */\n uint public reduceReservesBlockDelta;\n\n /**\n * @notice last block number at which reserves were reduced\n */\n uint public reduceReservesBlockNumber;\n\n /**\n * @notice address of protocol share reserve contract\n */\n address payable public protocolShareReserve;\n\n /**\n * @notice address of accessControlManager\n */\n\n address public accessControlManager;\n}\n\ncontract VTokenStorage is VTokenStorageBase {\n /**\n * @notice flashLoan is enabled for this market or not\n */\n bool public isFlashLoanEnabled;\n\n /**\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\n */\n uint256 public flashLoanFeeMantissa;\n\n /**\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\n */\n uint256 public flashLoanProtocolShareMantissa;\n\n /**\n * @notice Amount of flashLoan taken by the receiver\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\n */\n uint256 public flashLoanAmount;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\n */\n uint256 public internalCash;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n\nabstract contract VTokenInterface is VTokenStorage {\n /**\n * @notice Indicator that this is a vToken contract (for inspection)\n */\n bool public constant isVToken = true;\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are minted behalf by payer to receiver\n */\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are redeemed and fee is transferred\n */\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address liquidator,\n address borrower,\n uint repayAmount,\n address vTokenCollateral,\n uint seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModelV8 oldInterestRateModel,\n InterestRateModelV8 newInterestRateModel\n );\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint amount);\n\n /**\n * @notice Event emitted when block delta for reduce reserves get updated\n */\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\n\n /**\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Emitted when access control address is changed by admin\n */\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\n\n /**\n * @notice Event emitted when flashLoanEnabled status is changed\n */\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\n\n /**\n * @notice Event emitted when asset is transferred to receiver\n */\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\n\n /**\n * @notice Event emitted when asset is transferred from sender and verified\n */\n event TransferInUnderlyingFlashLoan(\n address indexed asset,\n address indexed sender,\n uint256 amount,\n uint256 totalFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /**\n * @notice Event emitted when excess tokens are swept by admin\n */\n event TokenSwept(address indexed recipient, uint256 amount);\n\n /**\n * @notice Event emitted when flashLoan fee mantissa is updated\n */\n event FlashLoanFeeUpdated(\n uint256 oldFlashLoanFeeMantissa,\n uint256 newFlashLoanFeeMantissa,\n uint256 oldFlashLoanProtocolShare,\n uint256 newFlashLoanProtocolShare\n );\n\n // @notice Thrown when comptroller is not valid\n error InvalidComptroller();\n\n // @notice Thrown when there is already an active flashLoan\n error FlashLoanAlreadyActive();\n\n /// @notice Thrown when flash loan fee exceeds maximum allowed\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\n\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\n\n // @notice Thrown when the vToken does not have enough cash to lend\n error InsufficientCash();\n\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\n\n /*** User Interface ***/\n\n function transfer(address dst, uint amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\n\n function approve(address spender, uint amount) external virtual returns (bool);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint);\n\n function totalBorrowsCurrent() external virtual returns (uint);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint);\n\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\n\n /*** Admin Function ***/\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\n\n /*** Admin Function ***/\n function _acceptAdmin() external virtual returns (uint);\n\n /*** Admin Function ***/\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\n\n /*** Admin Function ***/\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\n\n function balanceOf(address owner) external view virtual returns (uint);\n\n function allowance(address owner, address spender) external view virtual returns (uint);\n\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\n\n function borrowRatePerBlock() external view virtual returns (uint);\n\n function supplyRatePerBlock() external view virtual returns (uint);\n\n function getCash() external view virtual returns (uint);\n\n function exchangeRateCurrent() public virtual returns (uint);\n\n function accrueInterest() public virtual returns (uint);\n\n /*** Admin Function ***/\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\n\n /*** Admin Function ***/\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\n\n function borrowBalanceStored(address account) public view virtual returns (uint);\n\n function exchangeRateStored() public view virtual returns (uint);\n}\n\ninterface VBep20Interface {\n /*** User Interface ***/\n\n function mint(uint mintAmount) external returns (uint);\n\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\n\n function redeem(uint redeemTokens) external returns (uint);\n\n function redeemUnderlying(uint redeemAmount) external returns (uint);\n\n function borrow(uint borrowAmount) external returns (uint);\n\n function repayBorrow(uint repayAmount) external returns (uint);\n\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\n\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint);\n\n /*** Admin Functions ***/\n\n function _addReserves(uint addAmount) external returns (uint);\n}\n\ninterface VDelegatorInterface {\n /**\n * @notice Emitted when implementation is changed\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) external;\n}\n\ninterface VDelegateInterface {\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @dev Should revert if any issues arise which make it unfit for delegation\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) external;\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() external;\n}\n" + }, + "contracts/Tokens/XVS/IXVS.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\ninterface IXVS {\n /// @notice BEP-20 token name for this token\n function name() external pure returns (string memory);\n\n /// @notice BEP-20 token symbol for this token\n function symbol() external pure returns (string memory);\n\n /// @notice BEP-20 token decimals for this token\n function decimals() external pure returns (uint8);\n\n /// @notice Total number of tokens in circulation\n function totalSupply() external pure returns (uint256);\n\n /// @notice A record of each accounts delegate\n function delegates(address) external view returns (address);\n\n /// @notice A checkpoint for marking number of votes from a given block\n struct Checkpoint {\n uint32 fromBlock;\n uint96 votes;\n }\n\n /// @notice A record of votes checkpoints for each account, by index\n function checkpoints(address, uint32) external view returns (Checkpoint memory);\n\n /// @notice The number of checkpoints for each account\n function numCheckpoints(address) external view returns (uint32);\n\n /// @notice The EIP-712 typehash for the contract's domain\n function DOMAIN_TYPEHASH() external pure returns (bytes32);\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n function DELEGATION_TYPEHASH() external pure returns (bytes32);\n\n /// @notice A record of states for signing / validating signatures\n function nonces(address) external view returns (uint256);\n\n /// @notice An event thats emitted when an account changes its delegate\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /// @notice An event thats emitted when a delegate account's vote balance changes\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\n\n /// @notice The standard BEP-20 transfer event\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @notice The standard BEP-20 approval event\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\n * @param account The address of the account holding the funds\n * @param spender The address of the account spending the funds\n * @return The number of tokens approved\n */\n function allowance(address account, address spender) external view returns (uint);\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint rawAmount) external returns (bool);\n\n /**\n * @notice Get the number of tokens held by the `account`\n * @param account The address of the account to get the balance of\n * @return The number of tokens held\n */\n function balanceOf(address account) external view returns (uint);\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint rawAmount) external returns (bool);\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool);\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) external;\n\n /**\n * @notice Delegates votes from signatory to `delegatee`\n * @param delegatee The address to delegate votes to\n * @param nonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v The recovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getCurrentVotes(address account) external view returns (uint96);\n\n /**\n * @notice Determine the prior number of votes for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param blockNumber The block number to get the vote balance at\n * @return The number of votes the account had as of the given block\n */\n function getPriorVotes(address account, uint blockNumber) external view returns (uint96);\n}\n" + }, + "contracts/Utils/CarefulMath.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Careful Math\n * @author Venus\n * @notice Derived from OpenZeppelin's SafeMath library\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\n */\ncontract CarefulMath {\n /**\n * @dev Possible error codes that we can return\n */\n enum MathError {\n NO_ERROR,\n DIVISION_BY_ZERO,\n INTEGER_OVERFLOW,\n INTEGER_UNDERFLOW\n }\n\n /**\n * @dev Multiplies two numbers, returns an error on overflow.\n */\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (a == 0) {\n return (MathError.NO_ERROR, 0);\n }\n\n uint c;\n unchecked {\n c = a * b;\n }\n\n if (c / a != b) {\n return (MathError.INTEGER_OVERFLOW, 0);\n } else {\n return (MathError.NO_ERROR, c);\n }\n }\n\n /**\n * @dev Integer division of two numbers, truncating the quotient.\n */\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (b == 0) {\n return (MathError.DIVISION_BY_ZERO, 0);\n }\n\n return (MathError.NO_ERROR, a / b);\n }\n\n /**\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\n */\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (b <= a) {\n unchecked {\n return (MathError.NO_ERROR, a - b);\n }\n } else {\n return (MathError.INTEGER_UNDERFLOW, 0);\n }\n }\n\n /**\n * @dev Adds two numbers, returns an error on overflow.\n */\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\n uint c;\n unchecked {\n c = a + b;\n }\n\n if (c >= a) {\n return (MathError.NO_ERROR, c);\n } else {\n return (MathError.INTEGER_OVERFLOW, 0);\n }\n }\n\n /**\n * @dev add a and b and then subtract c\n */\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\n (MathError err0, uint sum) = addUInt(a, b);\n\n if (err0 != MathError.NO_ERROR) {\n return (err0, 0);\n }\n\n return subUInt(sum, c);\n }\n}\n" + }, + "contracts/Utils/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { WeightFunction } from \"../Comptroller/Diamond/interfaces/IFacetBase.sol\";\n\ncontract ComptrollerErrorReporter {\n /// @notice Thrown when You are already in the selected pool.\n error AlreadyInSelectedPool();\n\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\n error IncompatibleBorrowedAssets();\n\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\n\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\n error InvalidOperationForCorePool();\n\n /// @notice Thrown when input array lengths do not match\n error ArrayLengthMismatch();\n\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\n error MarketNotListedInCorePool();\n\n /// @notice Thrown when market is not set in the _poolMarkets mapping\n error MarketConfigNotFound();\n\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\n error BorrowNotAllowedInPool();\n\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\n error PoolMarketNotFound(uint96 poolId, address vToken);\n\n /// @notice Thrown when a given pool ID does not exist\n error PoolDoesNotExist(uint96 poolId);\n\n /// @notice Thrown when the pool label is empty\n error EmptyPoolLabel();\n\n /// @notice Thrown when a vToken is already listed in the specified pool\n error MarketAlreadyListed(uint96 poolId, address vToken);\n\n /// @notice Thrown when an invalid weighting strategy is provided\n error InvalidWeightingStrategy(WeightFunction strategy);\n\n // @notice Thrown when no assets are requested for flash loan\n error NoAssetsRequested();\n\n // @notice Thrown when invalid flash loan parameters are provided\n error InvalidFlashLoanParams();\n\n // @notice Thrown when flash loan is not enabled on the vToken\n error FlashLoanNotEnabled();\n\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\n error SenderNotAuthorizedForFlashLoan(address sender);\n\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\n error NotAnApprovedDelegate();\n\n // @notice Thrown when executeOperation on the receiver contract fails\n error ExecuteFlashLoanFailed();\n\n // @notice Thrown when the requested amount is zero\n error InvalidAmount();\n\n // @notice Thrown when failing to create a debt position in mode 1\n error FailedToCreateDebtPosition();\n\n /// @notice Thrown when attempting to interact with an inactive pool\n error InactivePool(uint96 poolId);\n\n /// @notice Thrown when repayment amount is insufficient to cover the fee\n error NotEnoughRepayment(uint256 repaid, uint256 required);\n\n /// @notice Thrown when the vToken market is not listed\n error MarketNotListed(address vToken);\n\n /// @notice Thrown when flash loans are paused system-wide\n error FlashLoanPausedSystemWide();\n\n /// @notice Thrown when too many assets are requested in a single flash loan\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\n\n enum Error {\n NO_ERROR,\n UNAUTHORIZED,\n COMPTROLLER_MISMATCH,\n INSUFFICIENT_SHORTFALL,\n INSUFFICIENT_LIQUIDITY,\n INVALID_CLOSE_FACTOR,\n INVALID_COLLATERAL_FACTOR,\n INVALID_LIQUIDATION_INCENTIVE,\n MARKET_NOT_ENTERED, // no longer possible\n MARKET_NOT_LISTED,\n MARKET_ALREADY_LISTED,\n MATH_ERROR,\n NONZERO_BORROW_BALANCE,\n PRICE_ERROR,\n REJECTION,\n SNAPSHOT_ERROR,\n TOO_MANY_ASSETS,\n TOO_MUCH_REPAY,\n INSUFFICIENT_BALANCE_FOR_VAI,\n MARKET_NOT_COLLATERAL,\n INVALID_LIQUIDATION_THRESHOLD\n }\n\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n EXIT_MARKET_BALANCE_OWED,\n EXIT_MARKET_REJECTION,\n SET_CLOSE_FACTOR_OWNER_CHECK,\n SET_CLOSE_FACTOR_VALIDATION,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_NO_EXISTS,\n SET_COLLATERAL_FACTOR_VALIDATION,\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\n SET_IMPLEMENTATION_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\n SET_PRICE_ORACLE_OWNER_CHECK,\n SUPPORT_MARKET_EXISTS,\n SUPPORT_MARKET_OWNER_CHECK,\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\n SET_VAI_MINT_RATE_CHECK,\n SET_VAICONTROLLER_OWNER_CHECK,\n SET_MINTED_VAI_REJECTION,\n SET_TREASURY_OWNER_CHECK,\n UNLIST_MARKET_NOT_LISTED,\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n\ncontract TokenErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED,\n BAD_INPUT,\n COMPTROLLER_REJECTION,\n COMPTROLLER_CALCULATION_ERROR,\n INTEREST_RATE_MODEL_ERROR,\n INVALID_ACCOUNT_PAIR,\n INVALID_CLOSE_AMOUNT_REQUESTED,\n INVALID_COLLATERAL_FACTOR,\n MATH_ERROR,\n MARKET_NOT_FRESH,\n MARKET_NOT_LISTED,\n TOKEN_INSUFFICIENT_ALLOWANCE,\n TOKEN_INSUFFICIENT_BALANCE,\n TOKEN_INSUFFICIENT_CASH,\n TOKEN_TRANSFER_IN_FAILED,\n TOKEN_TRANSFER_OUT_FAILED,\n TOKEN_PRICE_ERROR\n }\n\n /*\n * Note: FailureInfo (but not Error) is kept in alphabetical order\n * This is because FailureInfo grows significantly faster, and\n * the order of Error has some meaning, while the order of FailureInfo\n * is entirely arbitrary.\n */\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n BORROW_ACCRUE_INTEREST_FAILED,\n BORROW_CASH_NOT_AVAILABLE,\n BORROW_FRESHNESS_CHECK,\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n BORROW_MARKET_NOT_LISTED,\n BORROW_COMPTROLLER_REJECTION,\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n LIQUIDATE_COMPTROLLER_REJECTION,\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\n LIQUIDATE_FRESHNESS_CHECK,\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_SEIZE_TOO_MUCH,\n MINT_ACCRUE_INTEREST_FAILED,\n MINT_COMPTROLLER_REJECTION,\n MINT_EXCHANGE_CALCULATION_FAILED,\n MINT_EXCHANGE_RATE_READ_FAILED,\n MINT_FRESHNESS_CHECK,\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n MINT_TRANSFER_IN_FAILED,\n MINT_TRANSFER_IN_NOT_POSSIBLE,\n REDEEM_ACCRUE_INTEREST_FAILED,\n REDEEM_COMPTROLLER_REJECTION,\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\n REDEEM_EXCHANGE_RATE_READ_FAILED,\n REDEEM_FRESHNESS_CHECK,\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\n REDUCE_RESERVES_ADMIN_CHECK,\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\n REDUCE_RESERVES_FRESH_CHECK,\n REDUCE_RESERVES_VALIDATION,\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_COMPTROLLER_REJECTION,\n REPAY_BORROW_FRESHNESS_CHECK,\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_VALIDATION,\n SET_COMPTROLLER_OWNER_CHECK,\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_ORACLE_MARKET_NOT_LISTED,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\n SET_RESERVE_FACTOR_ADMIN_CHECK,\n SET_RESERVE_FACTOR_FRESH_CHECK,\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\n TRANSFER_COMPTROLLER_REJECTION,\n TRANSFER_NOT_ALLOWED,\n TRANSFER_NOT_ENOUGH,\n TRANSFER_TOO_MUCH,\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\n ADD_RESERVES_FRESH_CHECK,\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\n REPAY_VAI_COMPTROLLER_REJECTION,\n REPAY_VAI_FRESHNESS_CHECK,\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n\ncontract VAIControllerErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED, // The sender is not authorized to perform this action.\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\n MATH_ERROR, // A math calculation error occurred.\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\n }\n\n enum FailureInfo {\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\n SET_COMPTROLLER_OWNER_CHECK,\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n VAI_MINT_REJECTION,\n VAI_BURN_REJECTION,\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\n VAI_LIQUIDATE_FRESHNESS_CHECK,\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\n MINT_FEE_CALCULATION_FAILED,\n SET_TREASURY_OWNER_CHECK\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n" + }, + "contracts/Utils/Exponential.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { CarefulMath } from \"./CarefulMath.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Venus\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract Exponential is CarefulMath, ExponentialNoError {\n /**\n * @dev Creates an exponential from numerator and denominator values.\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\n * or if `denom` is zero.\n */\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\n }\n\n /**\n * @dev Adds two exponentials, returning a new exponential.\n */\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\n\n return (error, Exp({ mantissa: result }));\n }\n\n /**\n * @dev Subtracts two exponentials, returning a new exponential.\n */\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\n\n return (error, Exp({ mantissa: result }));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, returning a new Exp.\n */\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return (MathError.NO_ERROR, truncate(product));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return addUInt(truncate(product), addend);\n }\n\n /**\n * @dev Divide an Exp by a scalar, returning a new Exp.\n */\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\n }\n\n /**\n * @dev Divide a scalar by an Exp, returning a new Exp.\n */\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\n /*\n We are doing this as:\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\n\n How it works:\n Exp = a / b;\n Scalar = s;\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\n */\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n return getExp(numerator, divisor.mantissa);\n }\n\n /**\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\n */\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return (MathError.NO_ERROR, truncate(fraction));\n }\n\n /**\n * @dev Multiplies two exponentials, returning a new exponential.\n */\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n // We add half the scale before dividing so that we get rounding instead of truncation.\n // See \"Listing 6\" and text above it at https://accu.org/index.php/journals/1717\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({ mantissa: 0 }));\n }\n\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\n assert(err2 == MathError.NO_ERROR);\n\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\n }\n\n /**\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\n */\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\n }\n\n /**\n * @dev Multiplies three exponentials, returning a new exponential.\n */\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\n (MathError err, Exp memory ab) = mulExp(a, b);\n if (err != MathError.NO_ERROR) {\n return (err, ab);\n }\n return mulExp(ab, c);\n }\n\n /**\n * @dev Divides two exponentials, returning a new exponential.\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\n */\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n return getExp(a.mantissa, b.mantissa);\n }\n}\n" + }, + "contracts/Utils/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n uint internal constant expScale = 1e18;\n uint internal constant doubleScale = 1e36;\n uint internal constant halfExpScale = expScale / 2;\n uint internal constant mantissaOne = expScale;\n\n struct Exp {\n uint mantissa;\n }\n\n struct Double {\n uint mantissa;\n }\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / expScale;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\n Exp memory product = mul_(a, scalar);\n return truncate(product);\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n /**\n * @dev Checks if first Exp is less than second Exp.\n */\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa < right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp <= right Exp.\n */\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa <= right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp > right Exp.\n */\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa > right.mantissa;\n }\n\n /**\n * @dev returns true if Exp is exactly zero\n */\n function isZeroExp(Exp memory value) internal pure returns (bool) {\n return value.mantissa == 0;\n }\n\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\n require(n < 2 ** 224, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n require(n < 2 ** 32, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(uint a, uint b) internal pure returns (uint) {\n return add_(a, b, \"addition overflow\");\n }\n\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n uint c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(uint a, uint b) internal pure returns (uint) {\n return sub_(a, b, \"subtraction underflow\");\n }\n\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\n }\n\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\n return mul_(a, b.mantissa) / expScale;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\n }\n\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint a, Double memory b) internal pure returns (uint) {\n return mul_(a, b.mantissa) / doubleScale;\n }\n\n function mul_(uint a, uint b) internal pure returns (uint) {\n return mul_(a, b, \"multiplication overflow\");\n }\n\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n if (a == 0 || b == 0) {\n return 0;\n }\n uint c = a * b;\n require(c / a == b, errorMessage);\n return c;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\n }\n\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint a, Exp memory b) internal pure returns (uint) {\n return div_(mul_(a, expScale), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\n }\n\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint a, Double memory b) internal pure returns (uint) {\n return div_(mul_(a, doubleScale), b.mantissa);\n }\n\n function div_(uint a, uint b) internal pure returns (uint) {\n return div_(a, b, \"divide by zero\");\n }\n\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n function fraction(uint a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\n }\n}\n" + }, + "contracts/Utils/ReentrancyGuardTransient.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol\npragma solidity ^0.8.25;\n\nimport { TransientSlot } from \"./TransientSlot.sol\";\n\n/**\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\n *\n * NOTE: This variant only works on networks where EIP-1153 is available.\n *\n * _Available since v5.1._\n */\nabstract contract ReentrancyGuardTransient {\n using TransientSlot for *;\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n /**\n * @dev Unauthorized reentrant call.\n */\n error ReentrancyGuardReentrantCall();\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return REENTRANCY_GUARD_STORAGE.asBoolean().tload();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be NOT_ENTERED\n if (_reentrancyGuardEntered()) {\n revert ReentrancyGuardReentrantCall();\n }\n\n // Any calls to nonReentrant after this point will fail\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\n }\n\n function _nonReentrantAfter() private {\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\n }\n}\n" + }, + "contracts/Utils/TransientSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/TransientSlot.sol\npragma solidity ^0.8.25;\n\n/**\n * @dev Library for reading and writing value-types to specific transient storage slots.\n *\n * Transient slots are often used to store temporary values that are removed after the current transaction.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * * Example reading and writing values using transient storage:\n * ```solidity\n * contract Lock {\n * using TransientSlot for *;\n *\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\n *\n * modifier locked() {\n * require(!_LOCK_SLOT.asBoolean().tload());\n *\n * _LOCK_SLOT.asBoolean().tstore(true);\n * _;\n * _LOCK_SLOT.asBoolean().tstore(false);\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary TransientSlot {\n /**\n * @dev UDVT that represent a slot holding a address.\n */\n type AddressSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a AddressSlot.\n */\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\n return AddressSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a bool.\n */\n type BooleanSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a BooleanSlot.\n */\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\n return BooleanSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a bytes32.\n */\n type Bytes32Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Bytes32Slot.\n */\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\n return Bytes32Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a uint256.\n */\n type Uint256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Uint256Slot.\n */\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\n return Uint256Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a int256.\n */\n type Int256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Int256Slot.\n */\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\n return Int256Slot.wrap(slot);\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(AddressSlot slot) internal view returns (address value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(AddressSlot slot, address value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(BooleanSlot slot) internal view returns (bool value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(BooleanSlot slot, bool value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Bytes32Slot slot, bytes32 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Uint256Slot slot, uint256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Int256Slot slot) internal view returns (int256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Int256Slot slot, int256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "cancun", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/bscmainnet_addresses.json b/deployments/bscmainnet_addresses.json index 265512265..ac3b7f79e 100644 --- a/deployments/bscmainnet_addresses.json +++ b/deployments/bscmainnet_addresses.json @@ -69,14 +69,14 @@ "CheckpointView_From_WhitePaperInterestRateModel_base0bps_slope24000bps_bpy10512000_To_bpy21024000_At_1745903100": "0x9318f66729007281D4C4545c04b046C437bD77E5", "CheckpointView_From_WhitePaperInterestRateModel_base0bps_slope24000bps_bpy21024000_To_bpy42048000_At_1751250600": "0x170bE58D5C1983f03DC287AB9aBffC7DA16f862b", "CheckpointView_From_WhitePaperInterestRateModel_base0bps_slope24000bps_bpy42048000_To_bpy70080000_At_1768357800": "0x9E3f9A97285E2694Ea32c37EBFfE427492888edD", - "ComptrollerLens": "0x732138e18fa6f8f8E456ad829DB429A450a79758", + "ComptrollerLens": "0x75A71Ad878f6f24616A2AE21d046C0C8E72f67F8", "DAI": "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3", "DOGE": "0xbA2aE424d960c26247Dd6c32edC70B295c744C43", "DOT": "0x7083609fCE4d1d8Dc0C979AAb8c869Ea2C873402", "DefaultProxyAdmin": "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4", "ETH": "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", "FIL": "0x0D8Ce2A99Bb6e3B7Db580eD848240e4a0F9aE153", - "FlashLoanFacet": "0x72a284f144F2BE56549573DDFac2A90F8D662ed1", + "FlashLoanFacet": "0x7F00af2f30a55e79311392C98fBBfA629D19b3A5", "JumpRateModel_base0bps_slope10000bps_jump25000bps_kink8000bps_bpy10512000": "0x9e8fbACBfbD811Fc561af3Af7df8e38dEd4c52F3", "JumpRateModel_base0bps_slope10000bps_jump50000bps_kink8000bps_bpy10512000": "0x958F4C84d3ad523Fa9936Dc465A123C7AD43D69B", "JumpRateModel_base0bps_slope1000bps_jump20000bps_kink7500bps_bpy10512000": "0x871A82082482657B9df62Dea21509023F28c147C", @@ -157,7 +157,7 @@ "Liquidator_Implementation": "0xD65297007411694aA18c2941a5EB2b6ed4E0b819", "Liquidator_Proxy": "0x0870793286aada55d39ce7f82fb2766e8004cf43", "MATIC": "0xCC42724C6683B7E57334c4E856f4c9965ED682bD", - "MarketFacet": "0x87FdF72FA2fB29Cb43f03aCa261A8DC2C613a860", + "MarketFacet": "0x7397B6bcFA9332Cc8791c886F339B4D114651719", "MoveDebtDelegate": "0x89621C48EeC04A85AfadFD37d32077e65aFe2226", "MoveDebtDelegate_Implementation": "0x8439932C45e646FcC1009690417A65BF48f68Ce7", "MoveDebtDelegate_Proxy": "0x89621C48EeC04A85AfadFD37d32077e65aFe2226", @@ -165,17 +165,17 @@ "PegStability_USDT": "0xC138aa4E424D1A8539e8F38Af5a754a2B7c3Cc36", "PegStability_USDT_Implementation": "0x9664568e5131e85f67d87fCD55B249F5D25fa43e", "PegStability_USDT_Proxy": "0xC138aa4E424D1A8539e8F38Af5a754a2B7c3Cc36", - "PolicyFacet": "0x3C115aA5800A589D1E0c3163f3f562D5544F060f", + "PolicyFacet": "0x1CcDaf39085bae4e27c3Ba100561b1AD1B5A6b80", "Prime": "0xBbCD063efE506c3D42a0Fa2dB5C08430288C71FC", "PrimeLiquidityProvider": "0x23c4F844ffDdC6161174eB32c770D4D8C07833F2", "PrimeLiquidityProvider_Implementation": "0x46BED43b29D73835fF075bBa1A0002A1eD1E4de8", "PrimeLiquidityProvider_Proxy": "0x23c4F844ffDdC6161174eB32c770D4D8C07833F2", "Prime_Implementation": "0x1a6660059E61e88402bD34FC96C2332c5EeAF195", "Prime_Proxy": "0xBbCD063efE506c3D42a0Fa2dB5C08430288C71FC", - "RewardFacet": "0x7fcEc39e83f17469069b7A0f24A59B5BbEC0faBb", + "RewardFacet": "0xFaC00Dc856F454BB674c8588d4CC16Edef9dc28b", "SXP": "0x47BEAd2563dCBf3bF2c9407fEa4dC236fAbA485A", "SetCheckpointBscmainnet": "0x8f4C73dDb18875979803f9416bD42d8A1002457d", - "SetterFacet": "0x11B38582c61058eDd9a526561567B4c7b02060e7", + "SetterFacet": "0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0", "SnapshotLens": "0xDE876091531c92BFED078af29CAaD3dbd4157f7a", "SwapRouterCorePool": "0x8938E6dA30b59c1E27d5f70a94688A89F7c815a4", "TRX": "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3", @@ -206,7 +206,7 @@ "USDT": "0x55d398326f99059fF775485246999027B3197955", "UST": "0x3d4350cD54aeF9f9b2C29435e0fa809957B3F30a", "Unitroller": "0xfD36E2c2a6789Db23113685031d7F16329158384", - "Unitroller_Implementation": "0xB2243Da976F2cbAAa4dd1a76BF7F6EFbe22c4CFc", + "Unitroller_Implementation": "0x82cA18785BBbacBeD1C4f482921E2B2E989D8C08", "Unitroller_Proxy": "0xfD36E2c2a6789Db23113685031d7F16329158384", "VAI": "0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7", "VAIVault": "0x0B4d7776b87deD4a0958E32D5155598057D2620D", @@ -227,7 +227,7 @@ "VRTVaultProxy_Proxy": "0x98bF4786D72AAEF6c714425126Dd92f149e3F334", "VTreasury": "0xF322942f644A996A617BD29c16bd7d231d9F35E9", "VaiUnitroller": "0x004065D34C6b18cE4370ced1CeBDE94865DbFAFE", - "VaiUnitroller_Implementation": "0xFD754b21F5dbbf6eb282911Cc0112cbF88190767", + "VaiUnitroller_Implementation": "0x8A7d8589A597619A7842d3BC284b9a5a276FaE56", "VaiUnitroller_Proxy": "0x004065D34C6b18cE4370ced1CeBDE94865DbFAFE", "VenusChainlinkOracle": "0x7FabdD617200C9CB4dcf3dd2C41273e60552068A", "VenusLens": "0x344cD779C5aAF3436795B49f7C375E716A20f527", diff --git a/deployments/bsctestnet.json b/deployments/bsctestnet.json index b4c4febbb..3a2a14ffb 100644 --- a/deployments/bsctestnet.json +++ b/deployments/bsctestnet.json @@ -4552,7 +4552,7 @@ ] }, "ComptrollerLens": { - "address": "0x72dCB93F8c3fB00D31076e93b6E87C342A3eCC9c", + "address": "0xdBD0992dEd0a1EC14CE0532e60ea023F79372eD9", "abi": [ { "inputs": [], @@ -5596,7 +5596,7 @@ ] }, "FlashLoanFacet": { - "address": "0x32348c5bB52E5468A11901e70BdE061192feCAf4", + "address": "0x694ee0149bE810F68aEbf3D7969a79D760769B18", "abi": [ { "inputs": [], @@ -6157,6 +6157,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -20679,7 +20692,7 @@ ] }, "MarketFacet": { - "address": "0x8e0e15C99Ab0985cB39B2FE36532E5692730eBA9", + "address": "0xE160Afd62cAE8FCB16F6b702B325883dd80358d4", "abi": [ { "inputs": [], @@ -21392,6 +21405,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -28427,7 +28453,7 @@ ] }, "PolicyFacet": { - "address": "0xf8d94ef23c1188f8ab1009E56D558d7834d1F019", + "address": "0xDAfA77ED8b2CdF4dBE2D1aB27770eDE6A4a54463", "abi": [ { "inputs": [], @@ -29083,6 +29109,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -37823,7 +37862,7 @@ ] }, "RewardFacet": { - "address": "0x0bc7922Cc08Ea32E196d25805558a84dF54beC6a", + "address": "0x977515f4043111ba5e44C09D3Af071ba5B9B34a1", "abi": [ { "inputs": [], @@ -38527,6 +38566,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -39481,7 +39533,7 @@ ] }, "SetterFacet": { - "address": "0x4fc4C41388237D13A430879417f143EF54e5BB05", + "address": "0x38DC0fcEC79675c41f3e461797A7dd99EF3baC6E", "abi": [ { "inputs": [], @@ -40013,6 +40065,25 @@ "name": "NewComptrollerLens", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "oldDeviationBoundedOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "NewDeviationBoundedOracle", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -41004,6 +41075,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -41437,6 +41521,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "setDeviationBoundedOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -41994,7 +42097,7 @@ ] }, "SnapshotLens": { - "address": "0xBe9174A13577B016280aEc20a3b369C5BA272241", + "address": "0x88bB0AF511B5AB585460E7c36150Db82c28D9E5E", "abi": [ { "inputs": [ @@ -42060,7 +42163,17 @@ }, { "internalType": "uint256", - "name": "assetPrice", + "name": "spotPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "boundedCollateralPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "boundedDebtPrice", "type": "uint256" }, { @@ -42166,7 +42279,17 @@ }, { "internalType": "uint256", - "name": "assetPrice", + "name": "spotPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "boundedCollateralPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "boundedDebtPrice", "type": "uint256" }, { @@ -57429,7 +57552,7 @@ ] }, "Unitroller_Implementation": { - "address": "0x1774f993861B14B7C3963F3e09f67cfBd2B32198", + "address": "0xf00Ba2930E43C96719Ca40c8B5a48F4c9A004c52", "abi": [ { "anonymous": false, @@ -57648,6 +57771,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -68620,7 +68756,7 @@ ] }, "VaiUnitroller_Implementation": { - "address": "0xC1CE7174D58f177fd2b418292A6E60CDE9bACF78", + "address": "0xd2848305b0ee7646C930240D79549D50d6Ed024F", "abi": [ { "anonymous": false, diff --git a/deployments/bsctestnet/ComptrollerLens.json b/deployments/bsctestnet/ComptrollerLens.json index 4f10ebf5e..3187119fd 100644 --- a/deployments/bsctestnet/ComptrollerLens.json +++ b/deployments/bsctestnet/ComptrollerLens.json @@ -1,5 +1,5 @@ { - "address": "0x72dCB93F8c3fB00D31076e93b6E87C342A3eCC9c", + "address": "0xdBD0992dEd0a1EC14CE0532e60ea023F79372eD9", "abi": [ { "inputs": [], @@ -413,28 +413,28 @@ "type": "function" } ], - "transactionHash": "0xb345f0679425475b31f728cc8c81b2f35563a251f66f1a6e5bd5722e27df17fe", + "transactionHash": "0xe8b4b69080e014b1598cfd3b9bd4db5ada27995bde8376e686db08cdfd3e6ca6", "receipt": { "to": null, - "from": "0x33C6476F88eeA28D7E7900F759B4597704Ef95B7", - "contractAddress": "0x72dCB93F8c3fB00D31076e93b6E87C342A3eCC9c", - "transactionIndex": 0, - "gasUsed": "1179290", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0xdBD0992dEd0a1EC14CE0532e60ea023F79372eD9", + "transactionIndex": 2, + "gasUsed": "1283784", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1ced81c8f3afd7d615f6929e8222c9b6457e90c9f88565e4c4eafafea2f9a008", - "transactionHash": "0xb345f0679425475b31f728cc8c81b2f35563a251f66f1a6e5bd5722e27df17fe", + "blockHash": "0x76d627a5bcbb0e960e1c5557da5d5c7ef48a81cf3eb666a030e3e1f269c8975a", + "transactionHash": "0xe8b4b69080e014b1598cfd3b9bd4db5ada27995bde8376e686db08cdfd3e6ca6", "logs": [], - "blockNumber": 70275989, - "cumulativeGasUsed": "1179290", + "blockNumber": 102774708, + "cumulativeGasUsed": "1623096", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"},{\"internalType\":\"enum WeightFunction\",\"name\":\"weightingStrategy\",\"type\":\"uint8\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateVAICalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"getHypotheticalAccountLiquidity(address,address,address,uint256,uint256,uint8)\":{\"params\":{\"account\":\"Address of the borrowed vToken\",\"borrowAmount\":\"Amount borrowed\",\"comptroller\":\"Address of comptroller\",\"redeemTokens\":\"Number of vTokens being redeemed\",\"vTokenModify\":\"Address of collateral for vToken\",\"weightingStrategy\":\"The weighting strategy to use: - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\"},\"returns\":{\"_0\":\"Returns a tuple of error code, liquidity, and shortfall\"}},\"liquidateCalculateSeizeTokens(address,address,address,address,uint256)\":{\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of total borrowed amount\",\"borrower\":\"Address of borrower whose collateral is being seized\",\"comptroller\":\"Address of comptroller\",\"vTokenBorrowed\":\"Address of the borrowed vToken\",\"vTokenCollateral\":\"Address of collateral for the borrow\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"details\":\"This will be used only in vBNB\",\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of total borrowed amount\",\"comptroller\":\"Address of comptroller\",\"vTokenBorrowed\":\"Address of the borrowed vToken\",\"vTokenCollateral\":\"Address of collateral for the borrow\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}},\"liquidateVAICalculateSeizeTokens(address,address,uint256)\":{\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of the total borrowed amount\",\"comptroller\":\"Address of comptroller\",\"vTokenCollateral\":\"Address of collateral for vToken\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}}},\"title\":\"ComptrollerLens Contract\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"kind\":\"user\",\"methods\":{\"getHypotheticalAccountLiquidity(address,address,address,uint256,uint256,uint8)\":{\"notice\":\"Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow A snapshot of the account is taken and the total borrow amount of the account is calculated\"},\"liquidateCalculateSeizeTokens(address,address,address,address,uint256)\":{\"notice\":\"Computes the number of collateral tokens to be seized in a liquidation event\"},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"notice\":\"Computes the number of collateral tokens to be seized in a liquidation event\"},\"liquidateVAICalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Computes the number of VAI tokens to be seized in a liquidation event\"}},\"notice\":\"The ComptrollerLens contract has functions to get the number of tokens that can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/ComptrollerLens.sol\":\"ComptrollerLens\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/ComptrollerLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { ExponentialNoError } from \\\"../Utils/ExponentialNoError.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../Utils/ErrorReporter.sol\\\";\\nimport { ComptrollerInterface } from \\\"../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../Comptroller/ComptrollerLensInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title ComptrollerLens Contract\\n * @author Venus\\n * @notice The ComptrollerLens contract has functions to get the number of tokens that\\n * can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\\n */\\ncontract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, ExponentialNoError {\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint vTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp weightedFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\\n * @dev This will be used only in vBNB\\n * @param comptroller Address of comptroller\\n * @param vTokenBorrowed Address of the borrowed vToken\\n * @param vTokenCollateral Address of collateral for the borrow\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\\n\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\\n * @param borrower Address of borrower whose collateral is being seized\\n * @param comptroller Address of comptroller\\n * @param vTokenBorrowed Address of the borrowed vToken\\n * @param vTokenCollateral Address of collateral for the borrow\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getEffectiveLiquidationIncentive(\\n borrower,\\n vTokenCollateral\\n );\\n\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the number of VAI tokens to be seized in a liquidation event\\n * @param comptroller Address of comptroller\\n * @param vTokenCollateral Address of collateral for vToken\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of the total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = 1e18; // Note: this is VAI\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow\\n * A snapshot of the account is taken and the total borrow amount of the account is calculated\\n * @param comptroller Address of comptroller\\n * @param account Address of the borrowed vToken\\n * @param vTokenModify Address of collateral for vToken\\n * @param redeemTokens Number of vTokens being redeemed\\n * @param borrowAmount Amount borrowed\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return Returns a tuple of error code, liquidity, and shortfall\\n */\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint) {\\n (uint errorCode, AccountLiquidityLocalVars memory vars) = _calculateAccountPosition(\\n comptroller,\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n if (errorCode != 0) {\\n return (errorCode, 0, 0);\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (uint(Error.NO_ERROR), vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (uint(Error.NO_ERROR), 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Internal function to calculate account position\\n * @param comptroller Address of comptroller\\n * @param account Address of the account whose liquidity is being calculated\\n * @param vTokenModify The vToken being modified (redeemed or borrowed)\\n * @param redeemTokens Number of vTokens being redeemed\\n * @param borrowAmount Amount borrowed\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return oErr Returns an error code indicating success or failure\\n * @return vars Returns an AccountLiquidityLocalVars struct containing the calculated values\\n */\\n function _calculateAccountPosition(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint oErr, AccountLiquidityLocalVars memory vars) {\\n // For each asset the account is in\\n VToken[] memory assets = ComptrollerInterface(comptroller).getAssetsIn(account);\\n uint assetsCount = assets.length;\\n for (uint i = 0; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(\\n account\\n );\\n if (oErr != 0) {\\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (uint(Error.SNAPSHOT_ERROR), vars);\\n }\\n vars.weightedFactor = Exp({\\n mantissa: ComptrollerInterface(comptroller).getEffectiveLtvFactor(\\n account,\\n address(asset),\\n weightingStrategy\\n )\\n });\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(address(asset));\\n if (vars.oraclePriceMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), vars);\\n }\\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n\\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\\n vars.tokensToDenom = mul_(mul_(vars.weightedFactor, vars.exchangeRate), vars.oraclePrice);\\n\\n // sumCollateral += tokensToDenom * vTokenBalance\\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.vTokenBalance, vars.sumCollateral);\\n\\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.oraclePrice,\\n vars.borrowBalance,\\n vars.sumBorrowPlusEffects\\n );\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect\\n // sumBorrowPlusEffects += tokensToDenom * redeemTokens\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.tokensToDenom,\\n redeemTokens,\\n vars.sumBorrowPlusEffects\\n );\\n\\n // borrow effect\\n // sumBorrowPlusEffects += oraclePrice * borrowAmount\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.oraclePrice,\\n borrowAmount,\\n vars.sumBorrowPlusEffects\\n );\\n }\\n }\\n\\n VAIControllerInterface vaiController = ComptrollerInterface(comptroller).vaiController();\\n\\n if (address(vaiController) != address(0)) {\\n vars.sumBorrowPlusEffects = add_(vars.sumBorrowPlusEffects, vaiController.getVAIRepayAmount(account));\\n }\\n oErr = uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Calculate the number of tokens to seize during liquidation\\n * @param actualRepayAmount The amount of debt being repaid in the liquidation\\n * @param liquidationIncentiveMantissa The liquidation incentive, scaled by 1e18\\n * @param priceBorrowedMantissa The price of the borrowed asset, scaled by 1e18\\n * @param priceCollateralMantissa The price of the collateral asset, scaled by 1e18\\n * @param exchangeRateMantissa The exchange rate of the collateral asset, scaled by 1e18\\n * @return seizeTokens The number of tokens to seize during liquidation, scaled by 1e18\\n */\\n function _calculateSeizeTokens(\\n uint actualRepayAmount,\\n uint liquidationIncentiveMantissa,\\n uint priceBorrowedMantissa,\\n uint priceCollateralMantissa,\\n uint exchangeRateMantissa\\n ) internal pure returns (uint seizeTokens) {\\n Exp memory numerator = mul_(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n Exp({ mantissa: priceBorrowedMantissa })\\n );\\n Exp memory denominator = mul_(\\n Exp({ mantissa: priceCollateralMantissa }),\\n Exp({ mantissa: exchangeRateMantissa })\\n );\\n\\n seizeTokens = mul_ScalarTruncate(div_(numerator, denominator), actualRepayAmount);\\n }\\n}\\n\",\"keccak256\":\"0xefc0992c2559e8dfac700aa3c34f41f117d30f3e5de0f91be83e0113f83b1020\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506114588061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630ef332ca1461004e57806313d97e2c1461007b578063a5d5a0501461008e578063f7a9183e146100a1575b5f80fd5b61006161005c36600461108f565b6100cf565b604080519283526020830191909152015b60405180910390f35b6100616100893660046110dd565b61037b565b61006161009c36600461111b565b61055c565b6100b46100af36600461117b565b610811565b60408051938452602084019290925290820152606001610072565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013291906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c9190611205565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ff91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610245573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102699190611205565b9050811580610276575080155b1561028957600d5f935093505050610372565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102ea9190611205565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918b169063d686e9ee90602401602060405180830381865afa158015610333573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103579190611205565b90505f6103678883878787610892565b5f9750955050505050505b94509492505050565b5f805f670de0b6b3a764000090505f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610430573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104549190611205565b9050805f0361046b57600d5f935093505050610554565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104cc9190611205565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918a169063d686e9ee90602401602060405180830381865afa158015610515573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105399190611205565b90505f6105498883878787610892565b5f9750955050505050505b935093915050565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105bf91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610605573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106299190611205565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa1580156106d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f69190611205565b9050811580610703575080155b1561071657600d5f935093505050610807565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610753573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107779190611205565b60405163afd3783b60e01b81526001600160a01b038c8116600483015289811660248301529192505f918b169063afd3783b90604401602060405180830381865afa1580156107c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ec9190611205565b90505f6107fc8883878787610892565b5f9750955050505050505b9550959350505050565b5f805f805f6108248b8b8b8b8b8b610904565b91509150815f1461083d575092505f9150819050610886565b60208101518151111561086a575f6020820151825161085c9190611230565b5f9450945094505050610886565b5f815160208301515f9161087d91611230565b94509450945050505b96509650969350505050565b5f806108ba604051806020016040528088815250604051806020016040528088815250610d75565b90505f6108e3604051806020016040528087815250604051806020016040528087815250610d75565b90506108f86108f28383610dbc565b89610df4565b98975050505050505050565b5f61090d610fe0565b604051632aff3bff60e21b81526001600160a01b0388811660048301525f91908a169063abfceffc906024015f60405180830381865afa158015610953573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261097a9190810190611267565b80519091505f5b81811015610c72575f83828151811061099c5761099c61131b565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038d811660048301529192509082169063c37f68e290602401608060405180830381865afa1580156109ef573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a13919061132f565b60808901526060880152604087015295508515610a3857600f5b955050505050610d6a565b6040805160208101918290526319ef3e8b60e01b909152806001600160a01b038e166319ef3e8b610a6e8f868d60248701611362565b602060405180830381865afa158015610a89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aad9190611205565b905260c086015260408051602080820183526080880151825260e088019190915281516307dc0d1d60e41b815291516001600160a01b038f1692637dc0d1d09260048083019391928290030181865afa158015610b0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3091906111ea565b60405163fc57d4df60e01b81526001600160a01b038381166004830152919091169063fc57d4df90602401602060405180830381865afa158015610b76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9a9190611205565b60a086018190525f03610bae57600d610a2d565b604080516020810190915260a0860151815261010086015260c085015160e0860151610be891610bdd91610d75565b866101000151610d75565b610120860181905260408601518651610c02929190610e13565b855261010085015160608601516020870151610c1f929190610e13565b60208601526001600160a01b03808b1690821603610c6957610c4b8561012001518a8760200151610e13565b60208601819052610100860151610c63918a90610e13565b60208601525b50600101610981565b505f8a6001600160a01b0316639254f5e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cb0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cd491906111ea565b90506001600160a01b03811615610d63576020840151604051633c617c9160e11b81526001600160a01b038c81166004830152610d5d9291908416906378c2f92290602401602060405180830381865afa158015610d34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d589190611205565b610e3e565b60208501525b5f94505050505b965096945050505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610da7865f0151865f0151610e73565b610db191906113a4565b905290505b92915050565b60408051602081019091525f81526040518060200160405280610db1610ded865f0151670de0b6b3a7640000610e73565b8551610eb4565b5f80610e008484610ee6565b9050610e0b81610f0c565b949350505050565b5f80610e1f8585610ee6565b9050610e33610e2d82610f0c565b84610e3e565b9150505b9392505050565b5f610e378383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250610f23565b5f610e3783836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250610f65565b5f610e3783836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250610fb5565b60408051602081019091525f81526040518060200160405280610db1855f015185610e73565b80515f90610db690670de0b6b3a7640000906113a4565b5f80610f2f84866113c3565b90508285821015610f5c5760405162461bcd60e51b8152600401610f5391906113d6565b60405180910390fd5b50949350505050565b5f831580610f71575082155b15610f7d57505f610e37565b5f610f88848661140b565b905083610f9586836113a4565b148390610f5c5760405162461bcd60e51b8152600401610f5391906113d6565b5f8183610fd55760405162461bcd60e51b8152600401610f5391906113d6565b50610e0b83856113a4565b6040518061014001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f815260200161102560405180602001604052805f81525090565b815260200161103f60405180602001604052805f81525090565b815260200161105960405180602001604052805f81525090565b815260200161107360405180602001604052805f81525090565b905290565b6001600160a01b038116811461108c575f80fd5b50565b5f805f80608085870312156110a2575f80fd5b84356110ad81611078565b935060208501356110bd81611078565b925060408501356110cd81611078565b9396929550929360600135925050565b5f805f606084860312156110ef575f80fd5b83356110fa81611078565b9250602084013561110a81611078565b929592945050506040919091013590565b5f805f805f60a0868803121561112f575f80fd5b853561113a81611078565b9450602086013561114a81611078565b9350604086013561115a81611078565b9250606086013561116a81611078565b949793965091946080013592915050565b5f805f805f8060c08789031215611190575f80fd5b863561119b81611078565b955060208701356111ab81611078565b945060408701356111bb81611078565b9350606087013592506080870135915060a0870135600281106111dc575f80fd5b809150509295509295509295565b5f602082840312156111fa575f80fd5b8151610e3781611078565b5f60208284031215611215575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610db657610db661121c565b634e487b7160e01b5f52604160045260245ffd5b805161126281611078565b919050565b5f6020808385031215611278575f80fd5b825167ffffffffffffffff8082111561128f575f80fd5b818501915085601f8301126112a2575f80fd5b8151818111156112b4576112b4611243565b8060051b604051601f19603f830116810181811085821117156112d9576112d9611243565b6040529182528482019250838101850191888311156112f6575f80fd5b938501935b828510156108f85761130c85611257565b845293850193928501926112fb565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215611342575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061139657634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f826113be57634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610db657610db661121c565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082028115828204841417610db657610db661121c56fea2646970667358221220e8be33df18536bccf2d1e6d46cfdf853d20157902cc0f52c55cbf116e851f31264736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630ef332ca1461004e57806313d97e2c1461007b578063a5d5a0501461008e578063f7a9183e146100a1575b5f80fd5b61006161005c36600461108f565b6100cf565b604080519283526020830191909152015b60405180910390f35b6100616100893660046110dd565b61037b565b61006161009c36600461111b565b61055c565b6100b46100af36600461117b565b610811565b60408051938452602084019290925290820152606001610072565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061013291906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c9190611205565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ff91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610245573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102699190611205565b9050811580610276575080155b1561028957600d5f935093505050610372565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102ea9190611205565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918b169063d686e9ee90602401602060405180830381865afa158015610333573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103579190611205565b90505f6103678883878787610892565b5f9750955050505050505b94509492505050565b5f805f670de0b6b3a764000090505f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610430573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104549190611205565b9050805f0361046b57600d5f935093505050610554565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104cc9190611205565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918a169063d686e9ee90602401602060405180830381865afa158015610515573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105399190611205565b90505f6105498883878787610892565b5f9750955050505050505b935093915050565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105bf91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610605573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106299190611205565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c91906111ea565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa1580156106d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f69190611205565b9050811580610703575080155b1561071657600d5f935093505050610807565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610753573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107779190611205565b60405163afd3783b60e01b81526001600160a01b038c8116600483015289811660248301529192505f918b169063afd3783b90604401602060405180830381865afa1580156107c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ec9190611205565b90505f6107fc8883878787610892565b5f9750955050505050505b9550959350505050565b5f805f805f6108248b8b8b8b8b8b610904565b91509150815f1461083d575092505f9150819050610886565b60208101518151111561086a575f6020820151825161085c9190611230565b5f9450945094505050610886565b5f815160208301515f9161087d91611230565b94509450945050505b96509650969350505050565b5f806108ba604051806020016040528088815250604051806020016040528088815250610d75565b90505f6108e3604051806020016040528087815250604051806020016040528087815250610d75565b90506108f86108f28383610dbc565b89610df4565b98975050505050505050565b5f61090d610fe0565b604051632aff3bff60e21b81526001600160a01b0388811660048301525f91908a169063abfceffc906024015f60405180830381865afa158015610953573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261097a9190810190611267565b80519091505f5b81811015610c72575f83828151811061099c5761099c61131b565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038d811660048301529192509082169063c37f68e290602401608060405180830381865afa1580156109ef573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a13919061132f565b60808901526060880152604087015295508515610a3857600f5b955050505050610d6a565b6040805160208101918290526319ef3e8b60e01b909152806001600160a01b038e166319ef3e8b610a6e8f868d60248701611362565b602060405180830381865afa158015610a89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610aad9190611205565b905260c086015260408051602080820183526080880151825260e088019190915281516307dc0d1d60e41b815291516001600160a01b038f1692637dc0d1d09260048083019391928290030181865afa158015610b0c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b3091906111ea565b60405163fc57d4df60e01b81526001600160a01b038381166004830152919091169063fc57d4df90602401602060405180830381865afa158015610b76573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b9a9190611205565b60a086018190525f03610bae57600d610a2d565b604080516020810190915260a0860151815261010086015260c085015160e0860151610be891610bdd91610d75565b866101000151610d75565b610120860181905260408601518651610c02929190610e13565b855261010085015160608601516020870151610c1f929190610e13565b60208601526001600160a01b03808b1690821603610c6957610c4b8561012001518a8760200151610e13565b60208601819052610100860151610c63918a90610e13565b60208601525b50600101610981565b505f8a6001600160a01b0316639254f5e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610cb0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610cd491906111ea565b90506001600160a01b03811615610d63576020840151604051633c617c9160e11b81526001600160a01b038c81166004830152610d5d9291908416906378c2f92290602401602060405180830381865afa158015610d34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d589190611205565b610e3e565b60208501525b5f94505050505b965096945050505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610da7865f0151865f0151610e73565b610db191906113a4565b905290505b92915050565b60408051602081019091525f81526040518060200160405280610db1610ded865f0151670de0b6b3a7640000610e73565b8551610eb4565b5f80610e008484610ee6565b9050610e0b81610f0c565b949350505050565b5f80610e1f8585610ee6565b9050610e33610e2d82610f0c565b84610e3e565b9150505b9392505050565b5f610e378383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250610f23565b5f610e3783836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250610f65565b5f610e3783836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250610fb5565b60408051602081019091525f81526040518060200160405280610db1855f015185610e73565b80515f90610db690670de0b6b3a7640000906113a4565b5f80610f2f84866113c3565b90508285821015610f5c5760405162461bcd60e51b8152600401610f5391906113d6565b60405180910390fd5b50949350505050565b5f831580610f71575082155b15610f7d57505f610e37565b5f610f88848661140b565b905083610f9586836113a4565b148390610f5c5760405162461bcd60e51b8152600401610f5391906113d6565b5f8183610fd55760405162461bcd60e51b8152600401610f5391906113d6565b50610e0b83856113a4565b6040518061014001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f815260200161102560405180602001604052805f81525090565b815260200161103f60405180602001604052805f81525090565b815260200161105960405180602001604052805f81525090565b815260200161107360405180602001604052805f81525090565b905290565b6001600160a01b038116811461108c575f80fd5b50565b5f805f80608085870312156110a2575f80fd5b84356110ad81611078565b935060208501356110bd81611078565b925060408501356110cd81611078565b9396929550929360600135925050565b5f805f606084860312156110ef575f80fd5b83356110fa81611078565b9250602084013561110a81611078565b929592945050506040919091013590565b5f805f805f60a0868803121561112f575f80fd5b853561113a81611078565b9450602086013561114a81611078565b9350604086013561115a81611078565b9250606086013561116a81611078565b949793965091946080013592915050565b5f805f805f8060c08789031215611190575f80fd5b863561119b81611078565b955060208701356111ab81611078565b945060408701356111bb81611078565b9350606087013592506080870135915060a0870135600281106111dc575f80fd5b809150509295509295509295565b5f602082840312156111fa575f80fd5b8151610e3781611078565b5f60208284031215611215575f80fd5b5051919050565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610db657610db661121c565b634e487b7160e01b5f52604160045260245ffd5b805161126281611078565b919050565b5f6020808385031215611278575f80fd5b825167ffffffffffffffff8082111561128f575f80fd5b818501915085601f8301126112a2575f80fd5b8151818111156112b4576112b4611243565b8060051b604051601f19603f830116810181811085821117156112d9576112d9611243565b6040529182528482019250838101850191888311156112f6575f80fd5b938501935b828510156108f85761130c85611257565b845293850193928501926112fb565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215611342575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061139657634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f826113be57634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610db657610db661121c565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082028115828204841417610db657610db661121c56fea2646970667358221220e8be33df18536bccf2d1e6d46cfdf853d20157902cc0f52c55cbf116e851f31264736f6c63430008190033", + "numDeployments": 6, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"},{\"internalType\":\"enum WeightFunction\",\"name\":\"weightingStrategy\",\"type\":\"uint8\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"comptroller\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateVAICalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"getHypotheticalAccountLiquidity(address,address,address,uint256,uint256,uint8)\":{\"params\":{\"account\":\"Address of the borrowed vToken\",\"borrowAmount\":\"Amount borrowed\",\"comptroller\":\"Address of comptroller\",\"redeemTokens\":\"Number of vTokens being redeemed\",\"vTokenModify\":\"Address of collateral for vToken\",\"weightingStrategy\":\"The weighting strategy to use: - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\"},\"returns\":{\"_0\":\"Returns a tuple of error code, liquidity, and shortfall\"}},\"liquidateCalculateSeizeTokens(address,address,address,address,uint256)\":{\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of total borrowed amount\",\"borrower\":\"Address of borrower whose collateral is being seized\",\"comptroller\":\"Address of comptroller\",\"vTokenBorrowed\":\"Address of the borrowed vToken\",\"vTokenCollateral\":\"Address of collateral for the borrow\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"details\":\"This will be used only in vBNB\",\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of total borrowed amount\",\"comptroller\":\"Address of comptroller\",\"vTokenBorrowed\":\"Address of the borrowed vToken\",\"vTokenCollateral\":\"Address of collateral for the borrow\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}},\"liquidateVAICalculateSeizeTokens(address,address,uint256)\":{\"params\":{\"actualRepayAmount\":\"Repayment amount i.e amount to be repaid of the total borrowed amount\",\"comptroller\":\"Address of comptroller\",\"vTokenCollateral\":\"Address of collateral for vToken\"},\"returns\":{\"_0\":\"A tuple of error code, and tokens to seize\"}}},\"title\":\"ComptrollerLens Contract\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"kind\":\"user\",\"methods\":{\"getHypotheticalAccountLiquidity(address,address,address,uint256,uint256,uint8)\":{\"notice\":\"Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow A snapshot of the account is taken and the total borrow amount of the account is calculated\"},\"liquidateCalculateSeizeTokens(address,address,address,address,uint256)\":{\"notice\":\"Computes the number of collateral tokens to be seized in a liquidation event\"},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"notice\":\"Computes the number of collateral tokens to be seized in a liquidation event\"},\"liquidateVAICalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Computes the number of VAI tokens to be seized in a liquidation event\"}},\"notice\":\"The ComptrollerLens contract has functions to get the number of tokens that can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/ComptrollerLens.sol\":\"ComptrollerLens\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/ComptrollerLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { ExponentialNoError } from \\\"../Utils/ExponentialNoError.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../Utils/ErrorReporter.sol\\\";\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { ComptrollerInterface } from \\\"../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../Comptroller/ComptrollerLensInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title ComptrollerLens Contract\\n * @author Venus\\n * @notice The ComptrollerLens contract has functions to get the number of tokens that\\n * can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\\n */\\ncontract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, ExponentialNoError {\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountLiquidityLocalVars {\\n uint sumCollateral;\\n uint sumBorrowPlusEffects;\\n uint vTokenBalance;\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp weightedFactor;\\n Exp exchangeRate;\\n Exp tokensToDenom;\\n Exp collateralPrice;\\n Exp debtPrice;\\n IDeviationBoundedOracle boundedOracle;\\n ResilientOracleInterface spotOracle;\\n }\\n\\n /**\\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\\n * @dev This will be used only in vBNB\\n * @param comptroller Address of comptroller\\n * @param vTokenBorrowed Address of the borrowed vToken\\n * @param vTokenCollateral Address of collateral for the borrow\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\\n\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\\n * @param borrower Address of borrower whose collateral is being seized\\n * @param comptroller Address of comptroller\\n * @param vTokenBorrowed Address of the borrowed vToken\\n * @param vTokenCollateral Address of collateral for the borrow\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getEffectiveLiquidationIncentive(\\n borrower,\\n vTokenCollateral\\n );\\n\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the number of VAI tokens to be seized in a liquidation event\\n * @param comptroller Address of comptroller\\n * @param vTokenCollateral Address of collateral for vToken\\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of the total borrowed amount\\n * @return A tuple of error code, and tokens to seize\\n */\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint) {\\n /* Read oracle prices for borrowed and collateral markets */\\n uint priceBorrowedMantissa = 1e18; // Note: this is VAI\\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\\n if (priceCollateralMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), 0);\\n }\\n\\n /*\\n * Get the exchange rate and calculate the number of collateral tokens to seize:\\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\\n * seizeTokens = seizeAmount / exchangeRate\\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\\n */\\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\\n uint seizeTokens = _calculateSeizeTokens(\\n actualRepayAmount,\\n liquidationIncentiveMantissa,\\n priceBorrowedMantissa,\\n priceCollateralMantissa,\\n exchangeRateMantissa\\n );\\n\\n return (uint(Error.NO_ERROR), seizeTokens);\\n }\\n\\n /**\\n * @notice Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow\\n * A snapshot of the account is taken and the total borrow amount of the account is calculated\\n * @param comptroller Address of comptroller\\n * @param account Address of the borrowed vToken\\n * @param vTokenModify Address of collateral for vToken\\n * @param redeemTokens Number of vTokens being redeemed\\n * @param borrowAmount Amount borrowed\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return Returns a tuple of error code, liquidity, and shortfall\\n */\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint) {\\n (uint errorCode, AccountLiquidityLocalVars memory vars) = _calculateAccountPosition(\\n comptroller,\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n if (errorCode != 0) {\\n return (errorCode, 0, 0);\\n }\\n\\n // These are safe, as the underflow condition is checked first\\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\\n return (uint(Error.NO_ERROR), vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\\n } else {\\n return (uint(Error.NO_ERROR), 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\\n }\\n }\\n\\n /**\\n * @notice Computes an account's aggregate weighted-collateral and total-borrow values,\\n * optionally applying hypothetical redeem/borrow effects on a single market.\\n * @dev Pricing differs by weighting strategy:\\n * - USE_COLLATERAL_FACTOR: collateral is valued at `DeviationBoundedOracle.getBoundedCollateralPriceView`,\\n * borrows at `getBoundedDebtPriceView`.\\n * - USE_LIQUIDATION_THRESHOLD: both collateral and borrows use the spot oracle price.\\n * VAI borrows (from `vaiController.getVAIRepayAmount`) are added to `sumBorrowPlusEffects` after\\n * the per-asset loop, regardless of weighting strategy.\\n * @param comptroller Address of the comptroller whose markets and oracle are used\\n * @param account Address of the account whose position is being computed\\n * @param vTokenModify Market to apply hypothetical effects on; pass `VToken(address(0))` for none\\n * @param redeemTokens Number of vTokens hypothetically redeemed from `vTokenModify`\\n * @param borrowAmount Amount of underlying hypothetically borrowed from `vTokenModify`\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return oErr 0 on success, or a non-zero `Error` code (SNAPSHOT_ERROR or PRICE_ERROR) on failure\\n * @return vars Accumulated position data; `sumCollateral` and `sumBorrowPlusEffects` are the primary outputs\\n */\\n function _calculateAccountPosition(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint oErr, AccountLiquidityLocalVars memory vars) {\\n // For each asset the account is in\\n VToken[] memory assets = ComptrollerInterface(comptroller).getAssetsIn(account);\\n uint assetsCount = assets.length;\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n vars.boundedOracle = ComptrollerInterface(comptroller).deviationBoundedOracle();\\n } else {\\n vars.spotOracle = ComptrollerInterface(comptroller).oracle();\\n }\\n for (uint i = 0; i < assetsCount; ++i) {\\n VToken asset = assets[i];\\n\\n // Read the balances and exchange rate from the vToken\\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(\\n account\\n );\\n if (oErr != 0) {\\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (uint(Error.SNAPSHOT_ERROR), vars);\\n }\\n vars.weightedFactor = Exp({\\n mantissa: ComptrollerInterface(comptroller).getEffectiveLtvFactor(\\n account,\\n address(asset),\\n weightingStrategy\\n )\\n });\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n // Determine bounded prices for CF path\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n (uint256 collateralPriceMantissa, uint256 debtPriceMantissa) = vars.boundedOracle.getBoundedPricesView(\\n address(asset)\\n );\\n if (collateralPriceMantissa == 0 || debtPriceMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), vars);\\n }\\n vars.collateralPrice = Exp({ mantissa: collateralPriceMantissa });\\n vars.debtPrice = Exp({ mantissa: debtPriceMantissa });\\n } else {\\n // LT path \\u2014 always spot\\n vars.oraclePriceMantissa = vars.spotOracle.getUnderlyingPrice(address(asset));\\n if (vars.oraclePriceMantissa == 0) {\\n return (uint(Error.PRICE_ERROR), vars);\\n }\\n vars.collateralPrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n vars.debtPrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n }\\n\\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\\n vars.tokensToDenom = mul_(mul_(vars.weightedFactor, vars.exchangeRate), vars.collateralPrice);\\n\\n // sumCollateral += tokensToDenom * vTokenBalance\\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.vTokenBalance, vars.sumCollateral);\\n\\n // sumBorrowPlusEffects += debtPrice * borrowBalance\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.debtPrice,\\n vars.borrowBalance,\\n vars.sumBorrowPlusEffects\\n );\\n\\n // Calculate effects of interacting with vTokenModify\\n if (asset == vTokenModify) {\\n // redeem effect \\u2014 uses collateral-bounded tokensToDenom\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.tokensToDenom,\\n redeemTokens,\\n vars.sumBorrowPlusEffects\\n );\\n\\n // borrow effect \\u2014 uses debt-bounded price\\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\\n vars.debtPrice,\\n borrowAmount,\\n vars.sumBorrowPlusEffects\\n );\\n }\\n }\\n\\n VAIControllerInterface vaiController = ComptrollerInterface(comptroller).vaiController();\\n\\n if (address(vaiController) != address(0)) {\\n vars.sumBorrowPlusEffects = add_(vars.sumBorrowPlusEffects, vaiController.getVAIRepayAmount(account));\\n }\\n oErr = uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Calculate the number of tokens to seize during liquidation\\n * @param actualRepayAmount The amount of debt being repaid in the liquidation\\n * @param liquidationIncentiveMantissa The liquidation incentive, scaled by 1e18\\n * @param priceBorrowedMantissa The price of the borrowed asset, scaled by 1e18\\n * @param priceCollateralMantissa The price of the collateral asset, scaled by 1e18\\n * @param exchangeRateMantissa The exchange rate of the collateral asset, scaled by 1e18\\n * @return seizeTokens The number of tokens to seize during liquidation, scaled by 1e18\\n */\\n function _calculateSeizeTokens(\\n uint actualRepayAmount,\\n uint liquidationIncentiveMantissa,\\n uint priceBorrowedMantissa,\\n uint priceCollateralMantissa,\\n uint exchangeRateMantissa\\n ) internal pure returns (uint seizeTokens) {\\n Exp memory numerator = mul_(\\n Exp({ mantissa: liquidationIncentiveMantissa }),\\n Exp({ mantissa: priceBorrowedMantissa })\\n );\\n Exp memory denominator = mul_(\\n Exp({ mantissa: priceCollateralMantissa }),\\n Exp({ mantissa: exchangeRateMantissa })\\n );\\n\\n seizeTokens = mul_ScalarTruncate(div_(numerator, denominator), actualRepayAmount);\\n }\\n}\\n\",\"keccak256\":\"0x910f072609bc6200b550bb5498ec0d2a6603e75dc1da8a7b7e8f5f4846019ee4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b5061163b8061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630ef332ca1461004e57806313d97e2c1461007b578063a5d5a0501461008e578063f7a9183e146100a1575b5f80fd5b61006161005c36600461123c565b6100cf565b604080519283526020830191909152015b60405180910390f35b61006161008936600461128a565b61037b565b61006161009c3660046112c8565b61055c565b6100b46100af366004611328565b610811565b60408051938452602084019290925290820152606001610072565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101329190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c91906113b2565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ff9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610245573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061026991906113b2565b9050811580610276575080155b1561028957600d5f935093505050610372565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102ea91906113b2565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918b169063d686e9ee90602401602060405180830381865afa158015610333573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061035791906113b2565b90505f6103678883878787610892565b5f9750955050505050505b94509492505050565b5f805f670de0b6b3a764000090505f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610430573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061045491906113b2565b9050805f0361046b57600d5f935093505050610554565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104cc91906113b2565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918a169063d686e9ee90602401602060405180830381865afa158015610515573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053991906113b2565b90505f6105498883878787610892565b5f9750955050505050505b935093915050565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105bf9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610605573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062991906113b2565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa1580156106d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f691906113b2565b9050811580610703575080155b1561071657600d5f935093505050610807565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610753573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077791906113b2565b60405163afd3783b60e01b81526001600160a01b038c8116600483015289811660248301529192505f918b169063afd3783b90604401602060405180830381865afa1580156107c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ec91906113b2565b90505f6107fc8883878787610892565b5f9750955050505050505b9550959350505050565b5f805f805f6108248b8b8b8b8b8b610904565b91509150815f1461083d575092505f9150819050610886565b60208101518151111561086a575f6020820151825161085c91906113f1565b5f9450945094505050610886565b5f815160208301515f9161087d916113f1565b94509450945050505b96509650969350505050565b5f806108ba604051806020016040528088815250604051806020016040528088815250610efa565b90505f6108e3604051806020016040528087815250604051806020016040528087815250610efa565b90506108f86108f28383610f41565b89610f79565b98975050505050505050565b5f61090d611165565b604051632aff3bff60e21b81526001600160a01b0388811660048301525f91908a169063abfceffc906024015f60405180830381865afa158015610953573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261097a9190810190611428565b80519091505f856001811115610992576109926113c9565b03610a0b57896001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f79190611397565b6001600160a01b0316610160840152610a7b565b896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a47573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6b9190611397565b6001600160a01b03166101808401525b5f5b81811015610df7575f838281518110610a9857610a986114dc565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038d811660048301529192509082169063c37f68e290602401608060405180830381865afa158015610aeb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b0f91906114f0565b60808901526060880152604087015295508515610b3457600f5b955050505050610eef565b6040805160208101918290526319ef3e8b60e01b909152806001600160a01b038e166319ef3e8b610b6a8f868d60248701611523565b602060405180830381865afa158015610b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906113b2565b905260c086015260408051602081019091526080860151815260e08601525f876001811115610bda57610bda6113c9565b03610c9c576101608501516040516388142b6b60e01b81526001600160a01b0383811660048301525f9283929116906388142b6b906024016040805180830381865afa158015610c2c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c509190611565565b91509150815f1480610c60575080155b15610c7457600d9750505050505050610eef565b6040805160208082018352938152610120890152805192830190528152610140860152610d4d565b61018085015160405163fc57d4df60e01b81526001600160a01b0383811660048301529091169063fc57d4df90602401602060405180830381865afa158015610ce7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d0b91906113b2565b60a086018190525f03610d1f57600d610b29565b604080516020808201835260a088018051835261012089019290925282519081019092525181526101408601525b610d6d610d628660c001518760e00151610efa565b866101200151610efa565b610100860181905260408601518651610d87929190610f98565b855261014085015160608601516020870151610da4929190610f98565b60208601526001600160a01b03808b1690821603610dee57610dd08561010001518a8760200151610f98565b60208601819052610140860151610de8918a90610f98565b60208601525b50600101610a7d565b505f8a6001600160a01b0316639254f5e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e35573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e599190611397565b90506001600160a01b03811615610ee8576020840151604051633c617c9160e11b81526001600160a01b038c81166004830152610ee29291908416906378c2f92290602401602060405180830381865afa158015610eb9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610edd91906113b2565b610fc3565b60208501525b5f94505050505b965096945050505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610f2c865f0151865f0151610ff8565b610f369190611587565b905290505b92915050565b60408051602081019091525f81526040518060200160405280610f36610f72865f0151670de0b6b3a7640000610ff8565b8551611039565b5f80610f85848461106b565b9050610f9081611091565b949350505050565b5f80610fa4858561106b565b9050610fb8610fb282611091565b84610fc3565b9150505b9392505050565b5f610fbc8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b8152506110a8565b5f610fbc83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506110ea565b5f610fbc83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525061113a565b60408051602081019091525f81526040518060200160405280610f36855f015185610ff8565b80515f90610f3b90670de0b6b3a764000090611587565b5f806110b484866115a6565b905082858210156110e15760405162461bcd60e51b81526004016110d891906115b9565b60405180910390fd5b50949350505050565b5f8315806110f6575082155b1561110257505f610fbc565b5f61110d84866115ee565b90508361111a8683611587565b1483906110e15760405162461bcd60e51b81526004016110d891906115b9565b5f818361115a5760405162461bcd60e51b81526004016110d891906115b9565b50610f908385611587565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020016111aa60405180602001604052805f81525090565b81526020016111c460405180602001604052805f81525090565b81526020016111de60405180602001604052805f81525090565b81526020016111f860405180602001604052805f81525090565b815260200161121260405180602001604052805f81525090565b81525f6020820181905260409091015290565b6001600160a01b0381168114611239575f80fd5b50565b5f805f806080858703121561124f575f80fd5b843561125a81611225565b9350602085013561126a81611225565b9250604085013561127a81611225565b9396929550929360600135925050565b5f805f6060848603121561129c575f80fd5b83356112a781611225565b925060208401356112b781611225565b929592945050506040919091013590565b5f805f805f60a086880312156112dc575f80fd5b85356112e781611225565b945060208601356112f781611225565b9350604086013561130781611225565b9250606086013561131781611225565b949793965091946080013592915050565b5f805f805f8060c0878903121561133d575f80fd5b863561134881611225565b9550602087013561135881611225565b9450604087013561136881611225565b9350606087013592506080870135915060a087013560028110611389575f80fd5b809150509295509295509295565b5f602082840312156113a7575f80fd5b8151610fbc81611225565b5f602082840312156113c2575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b81810381811115610f3b57610f3b6113dd565b634e487b7160e01b5f52604160045260245ffd5b805161142381611225565b919050565b5f6020808385031215611439575f80fd5b825167ffffffffffffffff80821115611450575f80fd5b818501915085601f830112611463575f80fd5b81518181111561147557611475611404565b8060051b604051601f19603f8301168101818110858211171561149a5761149a611404565b6040529182528482019250838101850191888311156114b7575f80fd5b938501935b828510156108f8576114cd85611418565b845293850193928501926114bc565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215611503575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061155757634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f8060408385031215611576575f80fd5b505080516020909101519092909150565b5f826115a157634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610f3b57610f3b6113dd565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082028115828204841417610f3b57610f3b6113dd56fea2646970667358221220be12e4cb49f61f9a2a300e77e4aa08562c35b83a807c398740088c1815a96bcf64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061004a575f3560e01c80630ef332ca1461004e57806313d97e2c1461007b578063a5d5a0501461008e578063f7a9183e146100a1575b5f80fd5b61006161005c36600461123c565b6100cf565b604080519283526020830191909152015b60405180910390f35b61006161008936600461128a565b61037b565b61006161009c3660046112c8565b61055c565b6100b46100af366004611328565b610811565b60408051938452602084019290925290820152606001610072565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561010e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101329190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610178573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061019c91906113b2565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101db573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906101ff9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610245573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061026991906113b2565b9050811580610276575080155b1561028957600d5f935093505050610372565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906102ea91906113b2565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918b169063d686e9ee90602401602060405180830381865afa158015610333573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061035791906113b2565b90505f6103678883878787610892565b5f9750955050505050505b94509492505050565b5f805f670de0b6b3a764000090505f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156103c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ea9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610430573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061045491906113b2565b9050805f0361046b57600d5f935093505050610554565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa1580156104a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104cc91906113b2565b604051636b4374f760e11b81526001600160a01b0389811660048301529192505f918a169063d686e9ee90602401602060405180830381865afa158015610515573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061053991906113b2565b90505f6105498883878787610892565b5f9750955050505050505b935093915050565b5f805f866001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa15801561059b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105bf9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa158015610605573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061062991906113b2565b90505f876001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610668573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061068c9190611397565b60405163fc57d4df60e01b81526001600160a01b038881166004830152919091169063fc57d4df90602401602060405180830381865afa1580156106d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f691906113b2565b9050811580610703575080155b1561071657600d5f935093505050610807565b5f866001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610753573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061077791906113b2565b60405163afd3783b60e01b81526001600160a01b038c8116600483015289811660248301529192505f918b169063afd3783b90604401602060405180830381865afa1580156107c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107ec91906113b2565b90505f6107fc8883878787610892565b5f9750955050505050505b9550959350505050565b5f805f805f6108248b8b8b8b8b8b610904565b91509150815f1461083d575092505f9150819050610886565b60208101518151111561086a575f6020820151825161085c91906113f1565b5f9450945094505050610886565b5f815160208301515f9161087d916113f1565b94509450945050505b96509650969350505050565b5f806108ba604051806020016040528088815250604051806020016040528088815250610efa565b90505f6108e3604051806020016040528087815250604051806020016040528087815250610efa565b90506108f86108f28383610f41565b89610f79565b98975050505050505050565b5f61090d611165565b604051632aff3bff60e21b81526001600160a01b0388811660048301525f91908a169063abfceffc906024015f60405180830381865afa158015610953573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261097a9190810190611428565b80519091505f856001811115610992576109926113c9565b03610a0b57896001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f79190611397565b6001600160a01b0316610160840152610a7b565b896001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a47573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6b9190611397565b6001600160a01b03166101808401525b5f5b81811015610df7575f838281518110610a9857610a986114dc565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038d811660048301529192509082169063c37f68e290602401608060405180830381865afa158015610aeb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b0f91906114f0565b60808901526060880152604087015295508515610b3457600f5b955050505050610eef565b6040805160208101918290526319ef3e8b60e01b909152806001600160a01b038e166319ef3e8b610b6a8f868d60248701611523565b602060405180830381865afa158015610b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ba991906113b2565b905260c086015260408051602081019091526080860151815260e08601525f876001811115610bda57610bda6113c9565b03610c9c576101608501516040516388142b6b60e01b81526001600160a01b0383811660048301525f9283929116906388142b6b906024016040805180830381865afa158015610c2c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c509190611565565b91509150815f1480610c60575080155b15610c7457600d9750505050505050610eef565b6040805160208082018352938152610120890152805192830190528152610140860152610d4d565b61018085015160405163fc57d4df60e01b81526001600160a01b0383811660048301529091169063fc57d4df90602401602060405180830381865afa158015610ce7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d0b91906113b2565b60a086018190525f03610d1f57600d610b29565b604080516020808201835260a088018051835261012089019290925282519081019092525181526101408601525b610d6d610d628660c001518760e00151610efa565b866101200151610efa565b610100860181905260408601518651610d87929190610f98565b855261014085015160608601516020870151610da4929190610f98565b60208601526001600160a01b03808b1690821603610dee57610dd08561010001518a8760200151610f98565b60208601819052610140860151610de8918a90610f98565b60208601525b50600101610a7d565b505f8a6001600160a01b0316639254f5e56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e35573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e599190611397565b90506001600160a01b03811615610ee8576020840151604051633c617c9160e11b81526001600160a01b038c81166004830152610ee29291908416906378c2f92290602401602060405180830381865afa158015610eb9573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610edd91906113b2565b610fc3565b60208501525b5f94505050505b965096945050505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610f2c865f0151865f0151610ff8565b610f369190611587565b905290505b92915050565b60408051602081019091525f81526040518060200160405280610f36610f72865f0151670de0b6b3a7640000610ff8565b8551611039565b5f80610f85848461106b565b9050610f9081611091565b949350505050565b5f80610fa4858561106b565b9050610fb8610fb282611091565b84610fc3565b9150505b9392505050565b5f610fbc8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b8152506110a8565b5f610fbc83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506110ea565b5f610fbc83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525061113a565b60408051602081019091525f81526040518060200160405280610f36855f015185610ff8565b80515f90610f3b90670de0b6b3a764000090611587565b5f806110b484866115a6565b905082858210156110e15760405162461bcd60e51b81526004016110d891906115b9565b60405180910390fd5b50949350505050565b5f8315806110f6575082155b1561110257505f610fbc565b5f61110d84866115ee565b90508361111a8683611587565b1483906110e15760405162461bcd60e51b81526004016110d891906115b9565b5f818361115a5760405162461bcd60e51b81526004016110d891906115b9565b50610f908385611587565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020016111aa60405180602001604052805f81525090565b81526020016111c460405180602001604052805f81525090565b81526020016111de60405180602001604052805f81525090565b81526020016111f860405180602001604052805f81525090565b815260200161121260405180602001604052805f81525090565b81525f6020820181905260409091015290565b6001600160a01b0381168114611239575f80fd5b50565b5f805f806080858703121561124f575f80fd5b843561125a81611225565b9350602085013561126a81611225565b9250604085013561127a81611225565b9396929550929360600135925050565b5f805f6060848603121561129c575f80fd5b83356112a781611225565b925060208401356112b781611225565b929592945050506040919091013590565b5f805f805f60a086880312156112dc575f80fd5b85356112e781611225565b945060208601356112f781611225565b9350604086013561130781611225565b9250606086013561131781611225565b949793965091946080013592915050565b5f805f805f8060c0878903121561133d575f80fd5b863561134881611225565b9550602087013561135881611225565b9450604087013561136881611225565b9350606087013592506080870135915060a087013560028110611389575f80fd5b809150509295509295509295565b5f602082840312156113a7575f80fd5b8151610fbc81611225565b5f602082840312156113c2575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b81810381811115610f3b57610f3b6113dd565b634e487b7160e01b5f52604160045260245ffd5b805161142381611225565b919050565b5f6020808385031215611439575f80fd5b825167ffffffffffffffff80821115611450575f80fd5b818501915085601f830112611463575f80fd5b81518181111561147557611475611404565b8060051b604051601f19603f8301168101818110858211171561149a5761149a611404565b6040529182528482019250838101850191888311156114b7575f80fd5b938501935b828510156108f8576114cd85611418565b845293850193928501926114bc565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215611503575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061155757634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f8060408385031215611576575f80fd5b505080516020909101519092909150565b5f826115a157634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610f3b57610f3b6113dd565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b8082028115828204841417610f3b57610f3b6113dd56fea2646970667358221220be12e4cb49f61f9a2a300e77e4aa08562c35b83a807c398740088c1815a96bcf64736f6c63430008190033", "devdoc": { "author": "Venus", "events": { diff --git a/deployments/bsctestnet/FlashLoanFacet.json b/deployments/bsctestnet/FlashLoanFacet.json index 4e5c01353..eab427b7b 100644 --- a/deployments/bsctestnet/FlashLoanFacet.json +++ b/deployments/bsctestnet/FlashLoanFacet.json @@ -1,5 +1,5 @@ { - "address": "0x32348c5bB52E5468A11901e70BdE061192feCAf4", + "address": "0x694ee0149bE810F68aEbf3D7969a79D760769B18", "abi": [ { "inputs": [], @@ -560,6 +560,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1199,28 +1212,28 @@ "type": "function" } ], - "transactionHash": "0x972f54ff74d76fb3a0a0e304b0ef0b287a6bf0c417b2ca8bcca3e2614996e580", + "transactionHash": "0x15f7f327de386b4865406e34d17e1d2d9b9e28c933907dc7bec008b9867bc4aa", "receipt": { "to": null, - "from": "0x33C6476F88eeA28D7E7900F759B4597704Ef95B7", - "contractAddress": "0x32348c5bB52E5468A11901e70BdE061192feCAf4", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0x694ee0149bE810F68aEbf3D7969a79D760769B18", "transactionIndex": 0, - "gasUsed": "1510105", + "gasUsed": "1520957", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xce5b31444540ed03a05060daf6c971be401990a0b9a1bb4906c1833244fd6ff8", - "transactionHash": "0x972f54ff74d76fb3a0a0e304b0ef0b287a6bf0c417b2ca8bcca3e2614996e580", + "blockHash": "0xf85d66167e1f10141a9e4760611dc8b53c41181aaff6c56f4861fdca5f691296", + "transactionHash": "0x15f7f327de386b4865406e34d17e1d2d9b9e28c933907dc7bec008b9867bc4aa", "logs": [], - "blockNumber": 70275009, - "cumulativeGasUsed": "1510105", + "blockNumber": 102774088, + "cumulativeGasUsed": "1520957", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "7eb14bb68efebde544bca48fc6b525f5", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract VToken[]\",\"name\":\"assets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"FlashLoanExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repaidAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingDebt\",\"type\":\"uint256\"}],\"name\":\"FlashLoanRepaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FLASHLOAN_ASSETS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"underlyingAmounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"param\",\"type\":\"bytes\"}],\"name\":\"executeFlashLoan\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract implements flash loan functionality allowing users to borrow assets temporarily within a single transaction. Users can borrow multiple assets simultaneously and have the flexibility to repay partially, with unpaid balances automatically converted to debt positions. The contract supports protocol fee collection and integrates with the Venus lending protocol.\",\"errors\":{\"ReentrancyGuardReentrantCall()\":[{\"details\":\"Unauthorized reentrant call.\"}]},\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"executeFlashLoan(address,address,address[],uint256[],bytes)\":{\"custom:error\":\"FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.InvalidAmount is thrown if the requested amount is zero.TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.NoAssetsRequested is thrown if no assets are requested for the flash loan.InvalidFlashLoanParams is thrown if the flash loan params are invalid.MarketNotListed is thrown if the specified vToken market is not listed.SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\",\"custom:event\":\"Emits FlashLoanExecuted on success\",\"details\":\"Transfers the specified assets to the receiver contract and handles repayment.\",\"params\":{\"onBehalf\":\"The address of the user whose debt position will be used for the flashLoan.\",\"param\":\"The bytes passed in the executeOperation call.\",\"receiver\":\"The address of the contract that will receive the flashLoan amount and execute the operation.\",\"underlyingAmounts\":\"The amounts of each underlying assets to be loaned.\",\"vTokens\":\"The addresses of the vToken assets to be loaned.\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}}},\"title\":\"FlashLoanFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"FlashLoanExecuted(address,address[],uint256[])\":{\"notice\":\"Emitted when the flash loan is successfully executed\"},\"FlashLoanRepaid(address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when a flash loan is repaid (fully or partially) and shows debt position status\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"}},\"kind\":\"user\",\"methods\":{\"MAX_FLASHLOAN_ASSETS()\":{\"notice\":\"Maximum number of assets that can be flash loaned in a single transaction\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"executeFlashLoan(address,address,address[],uint256[],bytes)\":{\"notice\":\"Executes a flashLoan operation with the requested assets.\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contains all the methods related to flash loans\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol\":\"FlashLoanFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IFlashLoanFacet } from \\\"../interfaces/IFlashLoanFacet.sol\\\";\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { IFlashLoanReceiver } from \\\"../../../FlashLoan/interfaces/IFlashLoanReceiver.sol\\\";\\nimport { ReentrancyGuardTransient } from \\\"../../../Utils/ReentrancyGuardTransient.sol\\\";\\n\\n/**\\n * @title FlashLoanFacet\\n * @author Venus\\n * @notice This facet contains all the methods related to flash loans\\n * @dev This contract implements flash loan functionality allowing users to borrow assets temporarily\\n * within a single transaction. Users can borrow multiple assets simultaneously and have the\\n * flexibility to repay partially, with unpaid balances automatically converted to debt positions.\\n * The contract supports protocol fee collection and integrates with the Venus lending protocol.\\n */\\ncontract FlashLoanFacet is IFlashLoanFacet, FacetBase, ReentrancyGuardTransient {\\n /// @notice Maximum number of assets that can be flash loaned in a single transaction\\n uint256 public constant MAX_FLASHLOAN_ASSETS = 200;\\n\\n /// @notice Emitted when the flash loan is successfully executed\\n event FlashLoanExecuted(address indexed receiver, VToken[] assets, uint256[] amounts);\\n\\n /// @notice Emitted when a flash loan is repaid (fully or partially) and shows debt position status\\n event FlashLoanRepaid(\\n address indexed receiver,\\n address indexed onBehalf,\\n address indexed asset,\\n uint256 repaidAmount,\\n uint256 remainingDebt\\n );\\n\\n /**\\n * @notice Executes a flashLoan operation with the requested assets.\\n * @dev Transfers the specified assets to the receiver contract and handles repayment.\\n * @param onBehalf The address of the user whose debt position will be used for the flashLoan.\\n * @param receiver The address of the contract that will receive the flashLoan amount and execute the operation.\\n * @param vTokens The addresses of the vToken assets to be loaned.\\n * @param underlyingAmounts The amounts of each underlying assets to be loaned.\\n * @param param The bytes passed in the executeOperation call.\\n * @custom:error FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.\\n * @custom:error FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.\\n * @custom:error InvalidAmount is thrown if the requested amount is zero.\\n * @custom:error TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.\\n * @custom:error NoAssetsRequested is thrown if no assets are requested for the flash loan.\\n * @custom:error InvalidFlashLoanParams is thrown if the flash loan params are invalid.\\n * @custom:error MarketNotListed is thrown if the specified vToken market is not listed.\\n * @custom:error SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.\\n * @custom:error NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\\n * @custom:event Emits FlashLoanExecuted on success\\n */\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) external nonReentrant {\\n if (flashLoanPaused) {\\n revert FlashLoanPausedSystemWide();\\n }\\n\\n ensureNonzeroAddress(onBehalf);\\n\\n uint256 len = vTokens.length;\\n Market storage market;\\n\\n // vTokens array must not be empty\\n if (len == 0) {\\n revert NoAssetsRequested();\\n }\\n // Add maximum array length check to prevent gas limit issues\\n if (len > MAX_FLASHLOAN_ASSETS) {\\n revert TooManyAssetsRequested(len, MAX_FLASHLOAN_ASSETS);\\n }\\n\\n // All arrays must have the same length and not be zero\\n if (len != underlyingAmounts.length) {\\n revert InvalidFlashLoanParams();\\n }\\n\\n for (uint256 i; i < len; ++i) {\\n market = getCorePoolMarket(address(vTokens[i]));\\n if (!market.isListed) {\\n revert MarketNotListed(address(vTokens[i]));\\n }\\n if (!(vTokens[i]).isFlashLoanEnabled()) {\\n revert FlashLoanNotEnabled();\\n }\\n if (underlyingAmounts[i] == 0) {\\n revert InvalidAmount();\\n }\\n }\\n\\n ensureNonzeroAddress(receiver);\\n\\n if (!authorizedFlashLoan[msg.sender]) {\\n revert SenderNotAuthorizedForFlashLoan(msg.sender);\\n }\\n\\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\\n revert NotAnApprovedDelegate();\\n }\\n\\n // Execute flash loan phases\\n _executeFlashLoanPhases(onBehalf, receiver, vTokens, underlyingAmounts, param);\\n\\n emit FlashLoanExecuted(receiver, vTokens, underlyingAmounts);\\n }\\n\\n /**\\n * @notice Executes all flash loan phases in sequence\\n * @dev Orchestrates the complete flash loan process through three phases:\\n * Phase 1: Calculate fees and transfer assets to receiver\\n * Phase 2: Execute custom operations on receiver contract\\n * Phase 3: Handle repayment and debt position creation\\n * @param onBehalf The address whose debt position will be used for any unpaid flash loan balance\\n * @param receiver The address of the contract receiving the flash loan\\n * @param vTokens Array of vToken contracts for the assets being borrowed\\n * @param underlyingAmounts Array of amounts being borrowed for each asset\\n * @param param Additional parameters passed to the receiver contract\\n */\\n function _executeFlashLoanPhases(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) internal {\\n FlashLoanFee memory flashLoanData;\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n // Initialize arrays\\n flashLoanData.totalFees = new uint256[](vTokensLength);\\n flashLoanData.protocolFees = new uint256[](vTokensLength);\\n\\n // Phase 1: Calculate fees and transfer assets\\n _executePhase1(receiver, vTokens, underlyingAmounts, flashLoanData);\\n // Phase 2: Execute operations on receiver contract\\n uint256[] memory tokensApproved = _executePhase2(\\n onBehalf,\\n receiver,\\n vTokens,\\n underlyingAmounts,\\n flashLoanData.totalFees,\\n param\\n );\\n // Phase 3: Handles repayment\\n _executePhase3(onBehalf, receiver, vTokens, underlyingAmounts, tokensApproved, flashLoanData);\\n }\\n\\n /**\\n * @notice Phase 1: Calculate fees and transfer assets to receiver\\n * @dev For each requested asset:\\n * - Calculates total fee and protocol fee using the vToken's fee structure\\n * - Transfers the requested amount from the vToken to the receiver\\n * - Updates flash loan tracking in the vToken contract\\n * @param receiver The address receiving the flash loan assets\\n * @param vTokens Array of vToken contracts for the assets being borrowed\\n * @param underlyingAmounts Array of amounts being borrowed for each asset\\n * @param flashLoanData Struct containing fee arrays to be populated\\n */\\n function _executePhase1(\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n FlashLoanFee memory flashLoanData\\n ) internal {\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n (flashLoanData.totalFees[i], flashLoanData.protocolFees[i]) = vTokens[i].calculateFlashLoanFee(\\n underlyingAmounts[i]\\n );\\n\\n // Transfer the asset to receiver\\n vTokens[i].transferOutUnderlyingFlashLoan(receiver, underlyingAmounts[i]);\\n }\\n }\\n\\n /**\\n * @notice Phase 2: Execute custom operations on receiver contract\\n * @dev Calls the receiver contract's executeOperation function, allowing it to perform\\n * custom logic with the borrowed assets. The receiver must return success status\\n * and specify repayment amounts for each asset.\\n * @param onBehalf The address whose debt position will be used for any unpaid balance\\n * @param receiver The address of the contract executing custom operations\\n * @param vTokens Array of vToken contracts for the borrowed assets\\n * @param underlyingAmounts Array of amounts that were borrowed for each asset\\n * @param totalFees Array of total fees for each borrowed asset\\n * @param param Additional parameters passed to the receiver's executeOperation function\\n * @return tokensApproved Array of amounts the receiver approved for repayment\\n * @custom:error ExecuteFlashLoanFailed is thrown if the receiver's executeOperation returns false\\n */\\n function _executePhase2(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n uint256[] memory totalFees,\\n bytes memory param\\n ) internal returns (uint256[] memory) {\\n (bool success, uint256[] memory tokensApproved) = IFlashLoanReceiver(receiver).executeOperation(\\n vTokens,\\n underlyingAmounts,\\n totalFees,\\n msg.sender,\\n onBehalf,\\n param\\n );\\n\\n if (!success) {\\n revert ExecuteFlashLoanFailed();\\n }\\n return tokensApproved;\\n }\\n\\n /**\\n * @notice Phase 3: Handles repayment based on full or partial repayment\\n * @dev Processes repayment for each asset in the flash loan:\\n * - Ensures minimum fee repayment for each asset\\n * - Creates debt positions for any unpaid balances\\n * - Handles protocol fee distribution automatically\\n * @param onBehalf The address whose debt position will be used for any unpaid balance\\n * @param receiver The address providing the repayment\\n * @param vTokens Array of vToken contracts for the borrowed assets\\n * @param underlyingAmounts Array of amounts that were originally borrowed for each asset\\n * @param underlyingAmountsToRepay Array of amounts to be repaid for each asset\\n * @param flashLoanData Struct containing calculated fees for each asset\\n */\\n function _executePhase3(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n uint256[] memory underlyingAmountsToRepay,\\n FlashLoanFee memory flashLoanData\\n ) internal {\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n _handleFlashLoan(\\n vTokens[i],\\n onBehalf,\\n receiver,\\n underlyingAmounts[i],\\n underlyingAmountsToRepay[i],\\n flashLoanData.totalFees[i],\\n flashLoanData.protocolFees[i]\\n );\\n }\\n }\\n\\n /**\\n * @notice Handles the repayment and fee logic for a flash loan.\\n * @dev This function processes flash loan repayment with the following logic:\\n * 1. Ensures the repayment amount is at least equal to the total fee (minimum requirement).\\n * 2. Caps the repayment to prevent over-repayment (borrowedAmount + totalFee maximum).\\n * 3. Transfers the actual repayment amount from the receiver to the vToken.\\n * 4. If repayment is less than the full amount (borrowedAmount + totalFee), creates a debt position\\n * for the unpaid balance on the onBehalf address.\\n * 5. Protocol fees are automatically handled within the transferInUnderlyingFlashLoan function.\\n * @param vToken The vToken contract for the asset being flash loaned.\\n * @param onBehalf The address whose debt position will be used if there is any unpaid flash loan balance.\\n * @param receiver The address that received the flash loan and is providing the repayment.\\n * @param borrowedAmount The original amount that was borrowed (passed from underlyingAmounts).\\n * @param repayAmount The amount being repaid by the receiver (may be partial or full repayment).\\n * @param totalFee The total fee charged for the flash loan (minimum required repayment).\\n * @param protocolFee The portion of the total fee allocated to the protocol.\\n * @custom:error NotEnoughRepayment is thrown if repayAmount is less than the minimum required fee.\\n * @custom:error FailedToCreateDebtPosition is thrown if debt position creation fails for unpaid balance.\\n */\\n function _handleFlashLoan(\\n VToken vToken,\\n address payable onBehalf,\\n address payable receiver,\\n uint256 borrowedAmount,\\n uint256 repayAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) internal {\\n uint256 maxExpectedRepayment = borrowedAmount + totalFee;\\n uint256 actualRepayAmount = repayAmount > maxExpectedRepayment ? maxExpectedRepayment : repayAmount;\\n\\n if (actualRepayAmount < totalFee) {\\n revert NotEnoughRepayment(actualRepayAmount, totalFee);\\n }\\n\\n // Transfer repayment (this will handle the protocol fee as well)\\n uint256 actualAmountTransferred = vToken.transferInUnderlyingFlashLoan(\\n receiver,\\n actualRepayAmount,\\n totalFee,\\n protocolFee\\n );\\n\\n // Default for full repayment\\n uint256 leftUnpaidBalance;\\n\\n if (maxExpectedRepayment > actualAmountTransferred) {\\n // If there is any unpaid balance, it becomes an ongoing debt\\n leftUnpaidBalance = maxExpectedRepayment - actualAmountTransferred;\\n\\n uint256 debtError = vToken.flashLoanDebtPosition(onBehalf, leftUnpaidBalance);\\n if (debtError != 0) {\\n revert FailedToCreateDebtPosition();\\n }\\n }\\n\\n // Emit event for partial repayment with debt position creation\\n emit FlashLoanRepaid(\\n receiver,\\n onBehalf,\\n address(vToken.underlying()),\\n actualAmountTransferred,\\n leftUnpaidBalance\\n );\\n }\\n}\\n\",\"keccak256\":\"0x33aa51b0f084ec8653700c0e69b6464658bfd272bf3b0e4f4ee85e9c0ea01990\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFlashLoanFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IFlashLoanFacet {\\n /// @notice Data structure to hold flash loan related data during execution\\n struct FlashLoanFee {\\n uint256[] totalFees;\\n uint256[] protocolFees;\\n }\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) external;\\n}\\n\",\"keccak256\":\"0xc453824fde5313e97add12d484120817c1d5870ad17795161633d0538c6ee11e\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/FlashLoan/interfaces/IFlashLoanReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../Tokens/VTokens/VToken.sol\\\";\\n\\n/// @title IFlashLoanReceiver\\n/// @notice Interface for flashLoan receiver contract, which executes custom logic with flash-borrowed assets.\\n/// @dev This interface defines the method that must be implemented by any contract wishing to interact with the flashLoan system.\\n/// Contracts must ensure they have the means to repay at least the premium (fee), with any unpaid balance becoming debt.\\ninterface IFlashLoanReceiver {\\n /**\\n * @notice Executes an operation after receiving the flash-borrowed assets.\\n * @dev Implementation of this function must ensure at least the premium (fee) is repaid within the same transaction.\\n * Any unpaid balance (principal + premium - repaid amount) will be added to the onBehalf address's borrow balance.\\n * @param vTokens The vToken contracts corresponding to the flash-borrowed underlying assets.\\n * @param amounts The amounts of each underlying asset that were flash-borrowed.\\n * @param premiums The premiums (fees) associated with each flash-borrowed asset.\\n * @param initiator The address that initiated the flash loan.\\n * @param onBehalf The address of the user whose debt position will be used for any unpaid flash loan balance.\\n * @param param Additional parameters encoded as bytes. These can be used to pass custom data to the receiver contract.\\n * @return success True if the operation succeeds (regardless of repayment amount), false if the operation fails.\\n * @return repayAmounts Array of uint256 representing the amounts to be repaid for each asset. The receiver contract\\n * must approve these amounts to the respective vToken contracts before this function returns.\\n */\\n function executeOperation(\\n VToken[] calldata vTokens,\\n uint256[] calldata amounts,\\n uint256[] calldata premiums,\\n address initiator,\\n address onBehalf,\\n bytes calldata param\\n ) external returns (bool success, uint256[] memory repayAmounts);\\n}\\n\",\"keccak256\":\"0xe8eb540e98551178726f9d2d24e7ae1ab12ab96349c22f7232bacd377a0b33dd\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ReentrancyGuardTransient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)\\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol\\npragma solidity ^0.8.25;\\n\\nimport { TransientSlot } from \\\"./TransientSlot.sol\\\";\\n\\n/**\\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\\n *\\n * NOTE: This variant only works on networks where EIP-1153 is available.\\n *\\n * _Available since v5.1._\\n */\\nabstract contract ReentrancyGuardTransient {\\n using TransientSlot for *;\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.ReentrancyGuard\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\\n\\n /**\\n * @dev Unauthorized reentrant call.\\n */\\n error ReentrancyGuardReentrantCall();\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return REENTRANCY_GUARD_STORAGE.asBoolean().tload();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be NOT_ENTERED\\n if (_reentrancyGuardEntered()) {\\n revert ReentrancyGuardReentrantCall();\\n }\\n\\n // Any calls to nonReentrant after this point will fail\\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\\n }\\n\\n function _nonReentrantAfter() private {\\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\\n }\\n}\\n\",\"keccak256\":\"0xa27ad29257eb609e5d9ab43d3c84e68c7d22e0ea9bd9dbdc012250e7366d9604\",\"license\":\"MIT\"},\"contracts/Utils/TransientSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/TransientSlot.sol\\npragma solidity ^0.8.25;\\n\\n/**\\n * @dev Library for reading and writing value-types to specific transient storage slots.\\n *\\n * Transient slots are often used to store temporary values that are removed after the current transaction.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * * Example reading and writing values using transient storage:\\n * ```solidity\\n * contract Lock {\\n * using TransientSlot for *;\\n *\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\\n *\\n * modifier locked() {\\n * require(!_LOCK_SLOT.asBoolean().tload());\\n *\\n * _LOCK_SLOT.asBoolean().tstore(true);\\n * _;\\n * _LOCK_SLOT.asBoolean().tstore(false);\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\n */\\nlibrary TransientSlot {\\n /**\\n * @dev UDVT that represent a slot holding a address.\\n */\\n type AddressSlot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a AddressSlot.\\n */\\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\\n return AddressSlot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a bool.\\n */\\n type BooleanSlot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a BooleanSlot.\\n */\\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\\n return BooleanSlot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a bytes32.\\n */\\n type Bytes32Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Bytes32Slot.\\n */\\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\\n return Bytes32Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a uint256.\\n */\\n type Uint256Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Uint256Slot.\\n */\\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\\n return Uint256Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a int256.\\n */\\n type Int256Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Int256Slot.\\n */\\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\\n return Int256Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(AddressSlot slot) internal view returns (address value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(AddressSlot slot, address value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(BooleanSlot slot) internal view returns (bool value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(BooleanSlot slot, bool value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Bytes32Slot slot, bytes32 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Uint256Slot slot, uint256 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Int256Slot slot) internal view returns (int256 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Int256Slot slot, int256 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9ce486f12ba619221439564671d06e5d389b7ac1c72f18d0b08a1e26368a2765\",\"license\":\"MIT\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b50611a518061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106102e5575f3560e01c80638c1ac18a11610195578063c5f956af116100e4578063e0f6123d1161009e578063e875544611610079578063e8755446146107bc578063f445d703146107c5578063f851a440146107f2578063fa6331d814610804575f80fd5b8063e0f6123d14610750578063e37d4b7914610772578063e85a2960146107a9575f80fd5b8063c5f956af146106ea578063c7ee005e146106fd578063d3270f9914610710578063d463654c14610723578063dce154491461072a578063dcfbc0c71461073d575f80fd5b8063b2eafc391161014f578063bbb8864a1161012a578063bbb8864a14610683578063bec04f72146106a2578063bf32442d146106ab578063c5b4db55146106bc575f80fd5b8063b2eafc3914610602578063b8324c7c14610615578063bb82aa5e14610670575f80fd5b80638c1ac18a1461057c5780639254f5e51461059e57806394b2294b146105b157806396c99064146105ba5780639bb27d62146105dc578063a657e579146105ef575f80fd5b80634a58443211610251578063719f701b1161020b5780637d172bd5116101e65780637d172bd51461052a5780637dc0d1d01461053d5780637fb8e8cd146105505780638a7dc1651461055d575f80fd5b8063719f701b146104cf57806373769099146104d85780637655138314610518575f80fd5b80634a5844321461044e5780634d99c7761461046d578063517aa0c71461048057806352d84d1e146104885780635544ed9c1461049b5780635dd3fc9d146104b0575f80fd5b806324a3d622116102a257806324a3d622146103bf57806326782247146103d25780632bc7e29e146103e55780634088c73e1461040457806341a18d2c14610411578063425fad581461043b575f80fd5b806302c3bcbb146102e957806304ef9d581461031b57806308e0225c146103245780630db4b4e51461034e57806310b983381461035757806321af456914610394575b5f80fd5b6103086102f73660046113a4565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61030860225481565b6103086103323660046113c6565b601360209081525f928352604080842090915290825290205481565b610308601d5481565b6103846103653660046113c6565b602c60209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610312565b601e546103a7906001600160a01b031681565b6040516001600160a01b039091168152602001610312565b600a546103a7906001600160a01b031681565b6001546103a7906001600160a01b031681565b6103086103f33660046113a4565b60166020525f908152604090205481565b6018546103849060ff1681565b61030861041f3660046113c6565b601260209081525f928352604080842090915290825290205481565b6018546103849062010000900460ff1681565b61030861045c3660046113a4565b601f6020525f908152604090205481565b61030861047b366004611418565b61080d565b61030860c881565b6103a7610496366004611432565b61082e565b6104ae6104a9366004611589565b610856565b005b6103086104be3660046113a4565b602b6020525f908152604090205481565b610308601c5481565b6105006104e63660046113a4565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610312565b60185461038490610100900460ff1681565b601b546103a7906001600160a01b031681565b6004546103a7906001600160a01b031681565b6039546103849060ff1681565b61030861056b3660046113a4565b60146020525f908152604090205481565b61038461058a3660046113a4565b602d6020525f908152604090205460ff1681565b6015546103a7906001600160a01b031681565b61030860075481565b6105cd6105c836600461168e565b610b48565b604051610312939291906116d5565b6025546103a7906001600160a01b031681565b603754610500906001600160601b031681565b6020546103a7906001600160a01b031681565b61064c6106233660046113a4565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610312565b6002546103a7906001600160a01b031681565b6103086106913660046113a4565b602a6020525f908152604090205481565b61030860175481565b6033546001600160a01b03166103a7565b6106d26ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b039091168152602001610312565b6021546103a7906001600160a01b031681565b6031546103a7906001600160a01b031681565b6026546103a7906001600160a01b031681565b6105005f81565b6103a76107383660046116fe565b610bf5565b6003546103a7906001600160a01b031681565b61038461075e3660046113a4565b60386020525f908152604090205460ff1681565b61064c6107803660046113a4565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6103846107b7366004611728565b610c29565b61030860055481565b6103846107d33660046113c6565b603260209081525f928352604080842090915290825290205460ff1681565b5f546103a7906001600160a01b031681565b610308601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d818154811061083d575f80fd5b5f918252602090912001546001600160a01b0316905081565b61085e610c6d565b60395460ff1615610882576040516323118a8360e01b815260040160405180910390fd5b61088b85610cdc565b82515f8181036108ae5760405163bd96af5b60e01b815260040160405180910390fd5b60c88211156108df5760405163d2f1924360e01b81526004810183905260c860248201526044015b60405180910390fd5b835182146109005760405163aa6eb14560e01b815260040160405180910390fd5b5f5b82811015610a525761092c86828151811061091f5761091f611757565b6020026020010151610d2d565b805490925060ff1661097b5785818151811061094a5761094a611757565b6020026020010151604051635a9a1eb960e11b81526004016108d691906001600160a01b0391909116815260200190565b85818151811061098d5761098d611757565b60200260200101516001600160a01b031663ae3fcb1f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f4919061177a565b610a1157604051630a3fad8360e01b815260040160405180910390fd5b848181518110610a2357610a23611757565b60200260200101515f03610a4a5760405163162908e360e11b815260040160405180910390fd5b600101610902565b50610a5c86610cdc565b335f9081526038602052604090205460ff16610a8d576040516319d14ecf60e01b81523360048201526024016108d6565b336001600160a01b03881614801590610ac957506001600160a01b0387165f908152602c6020908152604080832033845290915290205460ff16155b15610ae7576040516337248ad960e01b815260040160405180910390fd5b610af48787878787610d4f565b856001600160a01b03167f785e5057f6e5f2e298f8dce2755a6ef29f9dd8a0f82a8b5cad101ea5ef803f048686604051610b2f929190611805565b60405180910390a25050610b41610e2a565b5050505050565b60366020525f9081526040902080548190610b6290611832565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8e90611832565b8015610bd95780601f10610bb057610100808354040283529160200191610bd9565b820191905f5260205f20905b815481529060010190602001808311610bbc57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6008602052815f5260405f208181548110610c0e575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610c5357610c5361186a565b815260208101919091526040015f205460ff169392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15610cad57604051633ee5aeb560e01b815260040160405180910390fd5b610cda60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90610e54565b565b6001600160a01b038116610d2a5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b60448201526064016108d6565b50565b5f60095f610d3b5f8561080d565b81526020019081526020015f209050919050565b604080518082019091526060808252602082015283518067ffffffffffffffff811115610d7e57610d7e611449565b604051908082528060200260200182016040528015610da7578160200160208202803683370190505b5082528067ffffffffffffffff811115610dc357610dc3611449565b604051908082528060200260200182016040528015610dec578160200160208202803683370190505b506020830152610dfe86868685610e5b565b5f610e1088888888875f015189610ffb565b9050610e208888888885886110a5565b5050505050505050565b610cda5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00610cd4565b80825d5050565b82515f5b81811015610ff357848181518110610e7957610e79611757565b60200260200101516001600160a01b03166371507cd5858381518110610ea157610ea1611757565b60200260200101516040518263ffffffff1660e01b8152600401610ec791815260200190565b6040805180830381865afa158015610ee1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f05919061187e565b8451805184908110610f1957610f19611757565b6020026020010185602001518481518110610f3657610f36611757565b6020026020010182815250828152505050848181518110610f5957610f59611757565b60200260200101516001600160a01b0316638d1f23d487868481518110610f8257610f82611757565b60200260200101516040518363ffffffff1660e01b8152600401610fbb9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b158015610fd2575f80fd5b505af1158015610fe4573d5f803e3d5ffd5b50505050806001019050610e5f565b505050505050565b60605f80876001600160a01b031663fc08f9f6888888338e8a6040518763ffffffff1660e01b8152600401611035969594939291906118a0565b5f604051808303815f875af1158015611050573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110779190810190611910565b915091508161109957604051635a3b2cbb60e11b815260040160405180910390fd5b98975050505050505050565b83515f5b81811015610e20576111448682815181106110c6576110c6611757565b602002602001015189898885815181106110e2576110e2611757565b60200260200101518886815181106110fc576110fc611757565b6020026020010151885f0151878151811061111957611119611757565b60200260200101518960200151888151811061113757611137611757565b602002602001015161114c565b6001016110a9565b5f61115783866119c3565b90505f8185116111675784611169565b815b9050838110156111965760405163bcb60bf360e01b815260048101829052602481018590526044016108d6565b60405163324235c960e11b81526001600160a01b0388811660048301526024820183905260448201869052606482018590525f91908b16906364846b92906084016020604051808303815f875af11580156111f3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061121791906119d6565b90505f818411156112c45761122c82856119ed565b6040516366ce8d7d60e01b81526001600160a01b038c81166004830152602482018390529192505f918d16906366ce8d7d906044016020604051808303815f875af115801561127d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a191906119d6565b905080156112c25760405163ab52b56f60e01b815260040160405180910390fd5b505b8a6001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611300573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113249190611a00565b6001600160a01b03168a6001600160a01b03168a6001600160a01b03167f499433c603d8d6db664daa76d7158679cc9f90c4c30723e29495a8c39302a173858560405161137b929190918252602082015260400190565b60405180910390a45050505050505050505050565b6001600160a01b0381168114610d2a575f80fd5b5f602082840312156113b4575f80fd5b81356113bf81611390565b9392505050565b5f80604083850312156113d7575f80fd5b82356113e281611390565b915060208301356113f281611390565b809150509250929050565b80356001600160601b0381168114611413575f80fd5b919050565b5f8060408385031215611429575f80fd5b6113e2836113fd565b5f60208284031215611442575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561148657611486611449565b604052919050565b5f67ffffffffffffffff8211156114a7576114a7611449565b5060051b60200190565b5f82601f8301126114c0575f80fd5b813560206114d56114d08361148e565b61145d565b8083825260208201915060208460051b8701019350868411156114f6575f80fd5b602086015b8481101561151257803583529183019183016114fb565b509695505050505050565b5f82601f83011261152c575f80fd5b813567ffffffffffffffff81111561154657611546611449565b611559601f8201601f191660200161145d565b81815284602083860101111561156d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a0868803121561159d575f80fd5b85356115a881611390565b94506020868101356115b981611390565b9450604087013567ffffffffffffffff808211156115d5575f80fd5b818901915089601f8301126115e8575f80fd5b81356115f66114d08261148e565b81815260059190911b8301840190848101908c831115611614575f80fd5b938501935b8285101561163b57843561162c81611390565b82529385019390850190611619565b975050506060890135925080831115611652575f80fd5b61165e8a848b016114b1565b94506080890135925080831115611673575f80fd5b50506116818882890161151d565b9150509295509295909350565b5f6020828403121561169e575f80fd5b6113bf826113fd565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6116e760608301866116a7565b931515602083015250901515604090910152919050565b5f806040838503121561170f575f80fd5b823561171a81611390565b946020939093013593505050565b5f8060408385031215611739575f80fd5b823561174481611390565b91506020830135600981106113f2575f80fd5b634e487b7160e01b5f52603260045260245ffd5b80518015158114611413575f80fd5b5f6020828403121561178a575f80fd5b6113bf8261176b565b5f815180845260208085019450602084015f5b838110156117cb5781516001600160a01b0316875295820195908201906001016117a6565b509495945050505050565b5f815180845260208085019450602084015f5b838110156117cb578151875295820195908201906001016117e9565b604081525f6118176040830185611793565b828103602084015261182981856117d6565b95945050505050565b600181811c9082168061184657607f821691505b60208210810361186457634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f806040838503121561188f575f80fd5b505080516020909101519092909150565b60c081525f6118b260c0830189611793565b82810360208401526118c481896117d6565b905082810360408401526118d881886117d6565b6001600160a01b0387811660608601528616608085015283810360a0850152905061190381856116a7565b9998505050505050505050565b5f8060408385031215611921575f80fd5b61192a8361176b565b915060208084015167ffffffffffffffff811115611946575f80fd5b8401601f81018613611956575f80fd5b80516119646114d08261148e565b81815260059190911b82018301908381019088831115611982575f80fd5b928401925b828410156119a057835182529284019290840190611987565b80955050505050509250929050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610828576108286119af565b5f602082840312156119e6575f80fd5b5051919050565b81810381811115610828576108286119af565b5f60208284031215611a10575f80fd5b81516113bf8161139056fea26469706673582212209cd3d81fb9d10e151925b12baabec95e8edecb883076621e2c24c076ac8c649a64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102e5575f3560e01c80638c1ac18a11610195578063c5f956af116100e4578063e0f6123d1161009e578063e875544611610079578063e8755446146107bc578063f445d703146107c5578063f851a440146107f2578063fa6331d814610804575f80fd5b8063e0f6123d14610750578063e37d4b7914610772578063e85a2960146107a9575f80fd5b8063c5f956af146106ea578063c7ee005e146106fd578063d3270f9914610710578063d463654c14610723578063dce154491461072a578063dcfbc0c71461073d575f80fd5b8063b2eafc391161014f578063bbb8864a1161012a578063bbb8864a14610683578063bec04f72146106a2578063bf32442d146106ab578063c5b4db55146106bc575f80fd5b8063b2eafc3914610602578063b8324c7c14610615578063bb82aa5e14610670575f80fd5b80638c1ac18a1461057c5780639254f5e51461059e57806394b2294b146105b157806396c99064146105ba5780639bb27d62146105dc578063a657e579146105ef575f80fd5b80634a58443211610251578063719f701b1161020b5780637d172bd5116101e65780637d172bd51461052a5780637dc0d1d01461053d5780637fb8e8cd146105505780638a7dc1651461055d575f80fd5b8063719f701b146104cf57806373769099146104d85780637655138314610518575f80fd5b80634a5844321461044e5780634d99c7761461046d578063517aa0c71461048057806352d84d1e146104885780635544ed9c1461049b5780635dd3fc9d146104b0575f80fd5b806324a3d622116102a257806324a3d622146103bf57806326782247146103d25780632bc7e29e146103e55780634088c73e1461040457806341a18d2c14610411578063425fad581461043b575f80fd5b806302c3bcbb146102e957806304ef9d581461031b57806308e0225c146103245780630db4b4e51461034e57806310b983381461035757806321af456914610394575b5f80fd5b6103086102f73660046113a4565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61030860225481565b6103086103323660046113c6565b601360209081525f928352604080842090915290825290205481565b610308601d5481565b6103846103653660046113c6565b602c60209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610312565b601e546103a7906001600160a01b031681565b6040516001600160a01b039091168152602001610312565b600a546103a7906001600160a01b031681565b6001546103a7906001600160a01b031681565b6103086103f33660046113a4565b60166020525f908152604090205481565b6018546103849060ff1681565b61030861041f3660046113c6565b601260209081525f928352604080842090915290825290205481565b6018546103849062010000900460ff1681565b61030861045c3660046113a4565b601f6020525f908152604090205481565b61030861047b366004611418565b61080d565b61030860c881565b6103a7610496366004611432565b61082e565b6104ae6104a9366004611589565b610856565b005b6103086104be3660046113a4565b602b6020525f908152604090205481565b610308601c5481565b6105006104e63660046113a4565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610312565b60185461038490610100900460ff1681565b601b546103a7906001600160a01b031681565b6004546103a7906001600160a01b031681565b6039546103849060ff1681565b61030861056b3660046113a4565b60146020525f908152604090205481565b61038461058a3660046113a4565b602d6020525f908152604090205460ff1681565b6015546103a7906001600160a01b031681565b61030860075481565b6105cd6105c836600461168e565b610b48565b604051610312939291906116d5565b6025546103a7906001600160a01b031681565b603754610500906001600160601b031681565b6020546103a7906001600160a01b031681565b61064c6106233660046113a4565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610312565b6002546103a7906001600160a01b031681565b6103086106913660046113a4565b602a6020525f908152604090205481565b61030860175481565b6033546001600160a01b03166103a7565b6106d26ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b039091168152602001610312565b6021546103a7906001600160a01b031681565b6031546103a7906001600160a01b031681565b6026546103a7906001600160a01b031681565b6105005f81565b6103a76107383660046116fe565b610bf5565b6003546103a7906001600160a01b031681565b61038461075e3660046113a4565b60386020525f908152604090205460ff1681565b61064c6107803660046113a4565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6103846107b7366004611728565b610c29565b61030860055481565b6103846107d33660046113c6565b603260209081525f928352604080842090915290825290205460ff1681565b5f546103a7906001600160a01b031681565b610308601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d818154811061083d575f80fd5b5f918252602090912001546001600160a01b0316905081565b61085e610c6d565b60395460ff1615610882576040516323118a8360e01b815260040160405180910390fd5b61088b85610cdc565b82515f8181036108ae5760405163bd96af5b60e01b815260040160405180910390fd5b60c88211156108df5760405163d2f1924360e01b81526004810183905260c860248201526044015b60405180910390fd5b835182146109005760405163aa6eb14560e01b815260040160405180910390fd5b5f5b82811015610a525761092c86828151811061091f5761091f611757565b6020026020010151610d2d565b805490925060ff1661097b5785818151811061094a5761094a611757565b6020026020010151604051635a9a1eb960e11b81526004016108d691906001600160a01b0391909116815260200190565b85818151811061098d5761098d611757565b60200260200101516001600160a01b031663ae3fcb1f6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109d0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109f4919061177a565b610a1157604051630a3fad8360e01b815260040160405180910390fd5b848181518110610a2357610a23611757565b60200260200101515f03610a4a5760405163162908e360e11b815260040160405180910390fd5b600101610902565b50610a5c86610cdc565b335f9081526038602052604090205460ff16610a8d576040516319d14ecf60e01b81523360048201526024016108d6565b336001600160a01b03881614801590610ac957506001600160a01b0387165f908152602c6020908152604080832033845290915290205460ff16155b15610ae7576040516337248ad960e01b815260040160405180910390fd5b610af48787878787610d4f565b856001600160a01b03167f785e5057f6e5f2e298f8dce2755a6ef29f9dd8a0f82a8b5cad101ea5ef803f048686604051610b2f929190611805565b60405180910390a25050610b41610e2a565b5050505050565b60366020525f9081526040902080548190610b6290611832565b80601f0160208091040260200160405190810160405280929190818152602001828054610b8e90611832565b8015610bd95780601f10610bb057610100808354040283529160200191610bd9565b820191905f5260205f20905b815481529060010190602001808311610bbc57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6008602052815f5260405f208181548110610c0e575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610c5357610c5361186a565b815260208101919091526040015f205460ff169392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15610cad57604051633ee5aeb560e01b815260040160405180910390fd5b610cda60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90610e54565b565b6001600160a01b038116610d2a5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b60448201526064016108d6565b50565b5f60095f610d3b5f8561080d565b81526020019081526020015f209050919050565b604080518082019091526060808252602082015283518067ffffffffffffffff811115610d7e57610d7e611449565b604051908082528060200260200182016040528015610da7578160200160208202803683370190505b5082528067ffffffffffffffff811115610dc357610dc3611449565b604051908082528060200260200182016040528015610dec578160200160208202803683370190505b506020830152610dfe86868685610e5b565b5f610e1088888888875f015189610ffb565b9050610e208888888885886110a5565b5050505050505050565b610cda5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00610cd4565b80825d5050565b82515f5b81811015610ff357848181518110610e7957610e79611757565b60200260200101516001600160a01b03166371507cd5858381518110610ea157610ea1611757565b60200260200101516040518263ffffffff1660e01b8152600401610ec791815260200190565b6040805180830381865afa158015610ee1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f05919061187e565b8451805184908110610f1957610f19611757565b6020026020010185602001518481518110610f3657610f36611757565b6020026020010182815250828152505050848181518110610f5957610f59611757565b60200260200101516001600160a01b0316638d1f23d487868481518110610f8257610f82611757565b60200260200101516040518363ffffffff1660e01b8152600401610fbb9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b158015610fd2575f80fd5b505af1158015610fe4573d5f803e3d5ffd5b50505050806001019050610e5f565b505050505050565b60605f80876001600160a01b031663fc08f9f6888888338e8a6040518763ffffffff1660e01b8152600401611035969594939291906118a0565b5f604051808303815f875af1158015611050573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110779190810190611910565b915091508161109957604051635a3b2cbb60e11b815260040160405180910390fd5b98975050505050505050565b83515f5b81811015610e20576111448682815181106110c6576110c6611757565b602002602001015189898885815181106110e2576110e2611757565b60200260200101518886815181106110fc576110fc611757565b6020026020010151885f0151878151811061111957611119611757565b60200260200101518960200151888151811061113757611137611757565b602002602001015161114c565b6001016110a9565b5f61115783866119c3565b90505f8185116111675784611169565b815b9050838110156111965760405163bcb60bf360e01b815260048101829052602481018590526044016108d6565b60405163324235c960e11b81526001600160a01b0388811660048301526024820183905260448201869052606482018590525f91908b16906364846b92906084016020604051808303815f875af11580156111f3573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061121791906119d6565b90505f818411156112c45761122c82856119ed565b6040516366ce8d7d60e01b81526001600160a01b038c81166004830152602482018390529192505f918d16906366ce8d7d906044016020604051808303815f875af115801561127d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112a191906119d6565b905080156112c25760405163ab52b56f60e01b815260040160405180910390fd5b505b8a6001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611300573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113249190611a00565b6001600160a01b03168a6001600160a01b03168a6001600160a01b03167f499433c603d8d6db664daa76d7158679cc9f90c4c30723e29495a8c39302a173858560405161137b929190918252602082015260400190565b60405180910390a45050505050505050505050565b6001600160a01b0381168114610d2a575f80fd5b5f602082840312156113b4575f80fd5b81356113bf81611390565b9392505050565b5f80604083850312156113d7575f80fd5b82356113e281611390565b915060208301356113f281611390565b809150509250929050565b80356001600160601b0381168114611413575f80fd5b919050565b5f8060408385031215611429575f80fd5b6113e2836113fd565b5f60208284031215611442575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561148657611486611449565b604052919050565b5f67ffffffffffffffff8211156114a7576114a7611449565b5060051b60200190565b5f82601f8301126114c0575f80fd5b813560206114d56114d08361148e565b61145d565b8083825260208201915060208460051b8701019350868411156114f6575f80fd5b602086015b8481101561151257803583529183019183016114fb565b509695505050505050565b5f82601f83011261152c575f80fd5b813567ffffffffffffffff81111561154657611546611449565b611559601f8201601f191660200161145d565b81815284602083860101111561156d575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a0868803121561159d575f80fd5b85356115a881611390565b94506020868101356115b981611390565b9450604087013567ffffffffffffffff808211156115d5575f80fd5b818901915089601f8301126115e8575f80fd5b81356115f66114d08261148e565b81815260059190911b8301840190848101908c831115611614575f80fd5b938501935b8285101561163b57843561162c81611390565b82529385019390850190611619565b975050506060890135925080831115611652575f80fd5b61165e8a848b016114b1565b94506080890135925080831115611673575f80fd5b50506116818882890161151d565b9150509295509295909350565b5f6020828403121561169e575f80fd5b6113bf826113fd565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6116e760608301866116a7565b931515602083015250901515604090910152919050565b5f806040838503121561170f575f80fd5b823561171a81611390565b946020939093013593505050565b5f8060408385031215611739575f80fd5b823561174481611390565b91506020830135600981106113f2575f80fd5b634e487b7160e01b5f52603260045260245ffd5b80518015158114611413575f80fd5b5f6020828403121561178a575f80fd5b6113bf8261176b565b5f815180845260208085019450602084015f5b838110156117cb5781516001600160a01b0316875295820195908201906001016117a6565b509495945050505050565b5f815180845260208085019450602084015f5b838110156117cb578151875295820195908201906001016117e9565b604081525f6118176040830185611793565b828103602084015261182981856117d6565b95945050505050565b600181811c9082168061184657607f821691505b60208210810361186457634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f806040838503121561188f575f80fd5b505080516020909101519092909150565b60c081525f6118b260c0830189611793565b82810360208401526118c481896117d6565b905082810360408401526118d881886117d6565b6001600160a01b0387811660608601528616608085015283810360a0850152905061190381856116a7565b9998505050505050505050565b5f8060408385031215611921575f80fd5b61192a8361176b565b915060208084015167ffffffffffffffff811115611946575f80fd5b8401601f81018613611956575f80fd5b80516119646114d08261148e565b81815260059190911b82018301908381019088831115611982575f80fd5b928401925b828410156119a057835182529284019290840190611987565b80955050505050509250929050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610828576108286119af565b5f602082840312156119e6575f80fd5b5051919050565b81810381811115610828576108286119af565b5f60208284031215611a10575f80fd5b81516113bf8161139056fea26469706673582212209cd3d81fb9d10e151925b12baabec95e8edecb883076621e2c24c076ac8c649a64736f6c63430008190033", + "numDeployments": 4, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ReentrancyGuardReentrantCall\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract VToken[]\",\"name\":\"assets\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"FlashLoanExecuted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repaidAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"remainingDebt\",\"type\":\"uint256\"}],\"name\":\"FlashLoanRepaid\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"MAX_FLASHLOAN_ASSETS\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"internalType\":\"address payable\",\"name\":\"receiver\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"underlyingAmounts\",\"type\":\"uint256[]\"},{\"internalType\":\"bytes\",\"name\":\"param\",\"type\":\"bytes\"}],\"name\":\"executeFlashLoan\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This contract implements flash loan functionality allowing users to borrow assets temporarily within a single transaction. Users can borrow multiple assets simultaneously and have the flexibility to repay partially, with unpaid balances automatically converted to debt positions. The contract supports protocol fee collection and integrates with the Venus lending protocol.\",\"errors\":{\"ReentrancyGuardReentrantCall()\":[{\"details\":\"Unauthorized reentrant call.\"}]},\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"executeFlashLoan(address,address,address[],uint256[],bytes)\":{\"custom:error\":\"FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.InvalidAmount is thrown if the requested amount is zero.TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.NoAssetsRequested is thrown if no assets are requested for the flash loan.InvalidFlashLoanParams is thrown if the flash loan params are invalid.MarketNotListed is thrown if the specified vToken market is not listed.SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\",\"custom:event\":\"Emits FlashLoanExecuted on success\",\"details\":\"Transfers the specified assets to the receiver contract and handles repayment.\",\"params\":{\"onBehalf\":\"The address of the user whose debt position will be used for the flashLoan.\",\"param\":\"The bytes passed in the executeOperation call.\",\"receiver\":\"The address of the contract that will receive the flashLoan amount and execute the operation.\",\"underlyingAmounts\":\"The amounts of each underlying assets to be loaned.\",\"vTokens\":\"The addresses of the vToken assets to be loaned.\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}}},\"title\":\"FlashLoanFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"FlashLoanExecuted(address,address[],uint256[])\":{\"notice\":\"Emitted when the flash loan is successfully executed\"},\"FlashLoanRepaid(address,address,address,uint256,uint256)\":{\"notice\":\"Emitted when a flash loan is repaid (fully or partially) and shows debt position status\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"}},\"kind\":\"user\",\"methods\":{\"MAX_FLASHLOAN_ASSETS()\":{\"notice\":\"Maximum number of assets that can be flash loaned in a single transaction\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"executeFlashLoan(address,address,address[],uint256[],bytes)\":{\"notice\":\"Executes a flashLoan operation with the requested assets.\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contains all the methods related to flash loans\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol\":\"FlashLoanFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IFlashLoanFacet } from \\\"../interfaces/IFlashLoanFacet.sol\\\";\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { IFlashLoanReceiver } from \\\"../../../FlashLoan/interfaces/IFlashLoanReceiver.sol\\\";\\nimport { ReentrancyGuardTransient } from \\\"../../../Utils/ReentrancyGuardTransient.sol\\\";\\n\\n/**\\n * @title FlashLoanFacet\\n * @author Venus\\n * @notice This facet contains all the methods related to flash loans\\n * @dev This contract implements flash loan functionality allowing users to borrow assets temporarily\\n * within a single transaction. Users can borrow multiple assets simultaneously and have the\\n * flexibility to repay partially, with unpaid balances automatically converted to debt positions.\\n * The contract supports protocol fee collection and integrates with the Venus lending protocol.\\n */\\ncontract FlashLoanFacet is IFlashLoanFacet, FacetBase, ReentrancyGuardTransient {\\n /// @notice Maximum number of assets that can be flash loaned in a single transaction\\n uint256 public constant MAX_FLASHLOAN_ASSETS = 200;\\n\\n /// @notice Emitted when the flash loan is successfully executed\\n event FlashLoanExecuted(address indexed receiver, VToken[] assets, uint256[] amounts);\\n\\n /// @notice Emitted when a flash loan is repaid (fully or partially) and shows debt position status\\n event FlashLoanRepaid(\\n address indexed receiver,\\n address indexed onBehalf,\\n address indexed asset,\\n uint256 repaidAmount,\\n uint256 remainingDebt\\n );\\n\\n /**\\n * @notice Executes a flashLoan operation with the requested assets.\\n * @dev Transfers the specified assets to the receiver contract and handles repayment.\\n * @param onBehalf The address of the user whose debt position will be used for the flashLoan.\\n * @param receiver The address of the contract that will receive the flashLoan amount and execute the operation.\\n * @param vTokens The addresses of the vToken assets to be loaned.\\n * @param underlyingAmounts The amounts of each underlying assets to be loaned.\\n * @param param The bytes passed in the executeOperation call.\\n * @custom:error FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.\\n * @custom:error FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.\\n * @custom:error InvalidAmount is thrown if the requested amount is zero.\\n * @custom:error TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.\\n * @custom:error NoAssetsRequested is thrown if no assets are requested for the flash loan.\\n * @custom:error InvalidFlashLoanParams is thrown if the flash loan params are invalid.\\n * @custom:error MarketNotListed is thrown if the specified vToken market is not listed.\\n * @custom:error SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.\\n * @custom:error NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\\n * @custom:event Emits FlashLoanExecuted on success\\n */\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) external nonReentrant {\\n if (flashLoanPaused) {\\n revert FlashLoanPausedSystemWide();\\n }\\n\\n ensureNonzeroAddress(onBehalf);\\n\\n uint256 len = vTokens.length;\\n Market storage market;\\n\\n // vTokens array must not be empty\\n if (len == 0) {\\n revert NoAssetsRequested();\\n }\\n // Add maximum array length check to prevent gas limit issues\\n if (len > MAX_FLASHLOAN_ASSETS) {\\n revert TooManyAssetsRequested(len, MAX_FLASHLOAN_ASSETS);\\n }\\n\\n // All arrays must have the same length and not be zero\\n if (len != underlyingAmounts.length) {\\n revert InvalidFlashLoanParams();\\n }\\n\\n for (uint256 i; i < len; ++i) {\\n market = getCorePoolMarket(address(vTokens[i]));\\n if (!market.isListed) {\\n revert MarketNotListed(address(vTokens[i]));\\n }\\n if (!(vTokens[i]).isFlashLoanEnabled()) {\\n revert FlashLoanNotEnabled();\\n }\\n if (underlyingAmounts[i] == 0) {\\n revert InvalidAmount();\\n }\\n }\\n\\n ensureNonzeroAddress(receiver);\\n\\n if (!authorizedFlashLoan[msg.sender]) {\\n revert SenderNotAuthorizedForFlashLoan(msg.sender);\\n }\\n\\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\\n revert NotAnApprovedDelegate();\\n }\\n\\n // Execute flash loan phases\\n _executeFlashLoanPhases(onBehalf, receiver, vTokens, underlyingAmounts, param);\\n\\n emit FlashLoanExecuted(receiver, vTokens, underlyingAmounts);\\n }\\n\\n /**\\n * @notice Executes all flash loan phases in sequence\\n * @dev Orchestrates the complete flash loan process through three phases:\\n * Phase 1: Calculate fees and transfer assets to receiver\\n * Phase 2: Execute custom operations on receiver contract\\n * Phase 3: Handle repayment and debt position creation\\n * @param onBehalf The address whose debt position will be used for any unpaid flash loan balance\\n * @param receiver The address of the contract receiving the flash loan\\n * @param vTokens Array of vToken contracts for the assets being borrowed\\n * @param underlyingAmounts Array of amounts being borrowed for each asset\\n * @param param Additional parameters passed to the receiver contract\\n */\\n function _executeFlashLoanPhases(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) internal {\\n FlashLoanFee memory flashLoanData;\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n // Initialize arrays\\n flashLoanData.totalFees = new uint256[](vTokensLength);\\n flashLoanData.protocolFees = new uint256[](vTokensLength);\\n\\n // Phase 1: Calculate fees and transfer assets\\n _executePhase1(receiver, vTokens, underlyingAmounts, flashLoanData);\\n // Phase 2: Execute operations on receiver contract\\n uint256[] memory tokensApproved = _executePhase2(\\n onBehalf,\\n receiver,\\n vTokens,\\n underlyingAmounts,\\n flashLoanData.totalFees,\\n param\\n );\\n // Phase 3: Handles repayment\\n _executePhase3(onBehalf, receiver, vTokens, underlyingAmounts, tokensApproved, flashLoanData);\\n }\\n\\n /**\\n * @notice Phase 1: Calculate fees and transfer assets to receiver\\n * @dev For each requested asset:\\n * - Calculates total fee and protocol fee using the vToken's fee structure\\n * - Transfers the requested amount from the vToken to the receiver\\n * - Updates flash loan tracking in the vToken contract\\n * @param receiver The address receiving the flash loan assets\\n * @param vTokens Array of vToken contracts for the assets being borrowed\\n * @param underlyingAmounts Array of amounts being borrowed for each asset\\n * @param flashLoanData Struct containing fee arrays to be populated\\n */\\n function _executePhase1(\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n FlashLoanFee memory flashLoanData\\n ) internal {\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n (flashLoanData.totalFees[i], flashLoanData.protocolFees[i]) = vTokens[i].calculateFlashLoanFee(\\n underlyingAmounts[i]\\n );\\n\\n // Transfer the asset to receiver\\n vTokens[i].transferOutUnderlyingFlashLoan(receiver, underlyingAmounts[i]);\\n }\\n }\\n\\n /**\\n * @notice Phase 2: Execute custom operations on receiver contract\\n * @dev Calls the receiver contract's executeOperation function, allowing it to perform\\n * custom logic with the borrowed assets. The receiver must return success status\\n * and specify repayment amounts for each asset.\\n * @param onBehalf The address whose debt position will be used for any unpaid balance\\n * @param receiver The address of the contract executing custom operations\\n * @param vTokens Array of vToken contracts for the borrowed assets\\n * @param underlyingAmounts Array of amounts that were borrowed for each asset\\n * @param totalFees Array of total fees for each borrowed asset\\n * @param param Additional parameters passed to the receiver's executeOperation function\\n * @return tokensApproved Array of amounts the receiver approved for repayment\\n * @custom:error ExecuteFlashLoanFailed is thrown if the receiver's executeOperation returns false\\n */\\n function _executePhase2(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n uint256[] memory totalFees,\\n bytes memory param\\n ) internal returns (uint256[] memory) {\\n (bool success, uint256[] memory tokensApproved) = IFlashLoanReceiver(receiver).executeOperation(\\n vTokens,\\n underlyingAmounts,\\n totalFees,\\n msg.sender,\\n onBehalf,\\n param\\n );\\n\\n if (!success) {\\n revert ExecuteFlashLoanFailed();\\n }\\n return tokensApproved;\\n }\\n\\n /**\\n * @notice Phase 3: Handles repayment based on full or partial repayment\\n * @dev Processes repayment for each asset in the flash loan:\\n * - Ensures minimum fee repayment for each asset\\n * - Creates debt positions for any unpaid balances\\n * - Handles protocol fee distribution automatically\\n * @param onBehalf The address whose debt position will be used for any unpaid balance\\n * @param receiver The address providing the repayment\\n * @param vTokens Array of vToken contracts for the borrowed assets\\n * @param underlyingAmounts Array of amounts that were originally borrowed for each asset\\n * @param underlyingAmountsToRepay Array of amounts to be repaid for each asset\\n * @param flashLoanData Struct containing calculated fees for each asset\\n */\\n function _executePhase3(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n uint256[] memory underlyingAmountsToRepay,\\n FlashLoanFee memory flashLoanData\\n ) internal {\\n //Cache array length\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n _handleFlashLoan(\\n vTokens[i],\\n onBehalf,\\n receiver,\\n underlyingAmounts[i],\\n underlyingAmountsToRepay[i],\\n flashLoanData.totalFees[i],\\n flashLoanData.protocolFees[i]\\n );\\n }\\n }\\n\\n /**\\n * @notice Handles the repayment and fee logic for a flash loan.\\n * @dev This function processes flash loan repayment with the following logic:\\n * 1. Ensures the repayment amount is at least equal to the total fee (minimum requirement).\\n * 2. Caps the repayment to prevent over-repayment (borrowedAmount + totalFee maximum).\\n * 3. Transfers the actual repayment amount from the receiver to the vToken.\\n * 4. If repayment is less than the full amount (borrowedAmount + totalFee), creates a debt position\\n * for the unpaid balance on the onBehalf address.\\n * 5. Protocol fees are automatically handled within the transferInUnderlyingFlashLoan function.\\n * @param vToken The vToken contract for the asset being flash loaned.\\n * @param onBehalf The address whose debt position will be used if there is any unpaid flash loan balance.\\n * @param receiver The address that received the flash loan and is providing the repayment.\\n * @param borrowedAmount The original amount that was borrowed (passed from underlyingAmounts).\\n * @param repayAmount The amount being repaid by the receiver (may be partial or full repayment).\\n * @param totalFee The total fee charged for the flash loan (minimum required repayment).\\n * @param protocolFee The portion of the total fee allocated to the protocol.\\n * @custom:error NotEnoughRepayment is thrown if repayAmount is less than the minimum required fee.\\n * @custom:error FailedToCreateDebtPosition is thrown if debt position creation fails for unpaid balance.\\n */\\n function _handleFlashLoan(\\n VToken vToken,\\n address payable onBehalf,\\n address payable receiver,\\n uint256 borrowedAmount,\\n uint256 repayAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) internal {\\n uint256 maxExpectedRepayment = borrowedAmount + totalFee;\\n uint256 actualRepayAmount = repayAmount > maxExpectedRepayment ? maxExpectedRepayment : repayAmount;\\n\\n if (actualRepayAmount < totalFee) {\\n revert NotEnoughRepayment(actualRepayAmount, totalFee);\\n }\\n\\n // Transfer repayment (this will handle the protocol fee as well)\\n uint256 actualAmountTransferred = vToken.transferInUnderlyingFlashLoan(\\n receiver,\\n actualRepayAmount,\\n totalFee,\\n protocolFee\\n );\\n\\n // Default for full repayment\\n uint256 leftUnpaidBalance;\\n\\n if (maxExpectedRepayment > actualAmountTransferred) {\\n // If there is any unpaid balance, it becomes an ongoing debt\\n leftUnpaidBalance = maxExpectedRepayment - actualAmountTransferred;\\n\\n uint256 debtError = vToken.flashLoanDebtPosition(onBehalf, leftUnpaidBalance);\\n if (debtError != 0) {\\n revert FailedToCreateDebtPosition();\\n }\\n }\\n\\n // Emit event for partial repayment with debt position creation\\n emit FlashLoanRepaid(\\n receiver,\\n onBehalf,\\n address(vToken.underlying()),\\n actualAmountTransferred,\\n leftUnpaidBalance\\n );\\n }\\n}\\n\",\"keccak256\":\"0x33aa51b0f084ec8653700c0e69b6464658bfd272bf3b0e4f4ee85e9c0ea01990\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFlashLoanFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IFlashLoanFacet {\\n /// @notice Data structure to hold flash loan related data during execution\\n struct FlashLoanFee {\\n uint256[] totalFees;\\n uint256[] protocolFees;\\n }\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] memory vTokens,\\n uint256[] memory underlyingAmounts,\\n bytes memory param\\n ) external;\\n}\\n\",\"keccak256\":\"0xc453824fde5313e97add12d484120817c1d5870ad17795161633d0538c6ee11e\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/FlashLoan/interfaces/IFlashLoanReceiver.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../Tokens/VTokens/VToken.sol\\\";\\n\\n/// @title IFlashLoanReceiver\\n/// @notice Interface for flashLoan receiver contract, which executes custom logic with flash-borrowed assets.\\n/// @dev This interface defines the method that must be implemented by any contract wishing to interact with the flashLoan system.\\n/// Contracts must ensure they have the means to repay at least the premium (fee), with any unpaid balance becoming debt.\\ninterface IFlashLoanReceiver {\\n /**\\n * @notice Executes an operation after receiving the flash-borrowed assets.\\n * @dev Implementation of this function must ensure at least the premium (fee) is repaid within the same transaction.\\n * Any unpaid balance (principal + premium - repaid amount) will be added to the onBehalf address's borrow balance.\\n * @param vTokens The vToken contracts corresponding to the flash-borrowed underlying assets.\\n * @param amounts The amounts of each underlying asset that were flash-borrowed.\\n * @param premiums The premiums (fees) associated with each flash-borrowed asset.\\n * @param initiator The address that initiated the flash loan.\\n * @param onBehalf The address of the user whose debt position will be used for any unpaid flash loan balance.\\n * @param param Additional parameters encoded as bytes. These can be used to pass custom data to the receiver contract.\\n * @return success True if the operation succeeds (regardless of repayment amount), false if the operation fails.\\n * @return repayAmounts Array of uint256 representing the amounts to be repaid for each asset. The receiver contract\\n * must approve these amounts to the respective vToken contracts before this function returns.\\n */\\n function executeOperation(\\n VToken[] calldata vTokens,\\n uint256[] calldata amounts,\\n uint256[] calldata premiums,\\n address initiator,\\n address onBehalf,\\n bytes calldata param\\n ) external returns (bool success, uint256[] memory repayAmounts);\\n}\\n\",\"keccak256\":\"0xe8eb540e98551178726f9d2d24e7ae1ab12ab96349c22f7232bacd377a0b33dd\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ReentrancyGuardTransient.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)\\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol\\npragma solidity ^0.8.25;\\n\\nimport { TransientSlot } from \\\"./TransientSlot.sol\\\";\\n\\n/**\\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\\n *\\n * NOTE: This variant only works on networks where EIP-1153 is available.\\n *\\n * _Available since v5.1._\\n */\\nabstract contract ReentrancyGuardTransient {\\n using TransientSlot for *;\\n\\n // keccak256(abi.encode(uint256(keccak256(\\\"openzeppelin.storage.ReentrancyGuard\\\")) - 1)) & ~bytes32(uint256(0xff))\\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\\n\\n /**\\n * @dev Unauthorized reentrant call.\\n */\\n error ReentrancyGuardReentrantCall();\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n * Calling a `nonReentrant` function from another `nonReentrant`\\n * function is not supported. It is possible to prevent this from happening\\n * by making the `nonReentrant` function external, and making it call a\\n * `private` function that does the actual work.\\n */\\n modifier nonReentrant() {\\n _nonReentrantBefore();\\n _;\\n _nonReentrantAfter();\\n }\\n\\n /**\\n * @dev Returns true if the reentrancy guard is currently set to \\\"entered\\\", which indicates there is a\\n * `nonReentrant` function in the call stack.\\n */\\n function _reentrancyGuardEntered() internal view returns (bool) {\\n return REENTRANCY_GUARD_STORAGE.asBoolean().tload();\\n }\\n\\n function _nonReentrantBefore() private {\\n // On the first call to nonReentrant, _status will be NOT_ENTERED\\n if (_reentrancyGuardEntered()) {\\n revert ReentrancyGuardReentrantCall();\\n }\\n\\n // Any calls to nonReentrant after this point will fail\\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\\n }\\n\\n function _nonReentrantAfter() private {\\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\\n }\\n}\\n\",\"keccak256\":\"0xa27ad29257eb609e5d9ab43d3c84e68c7d22e0ea9bd9dbdc012250e7366d9604\",\"license\":\"MIT\"},\"contracts/Utils/TransientSlot.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)\\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/TransientSlot.sol\\npragma solidity ^0.8.25;\\n\\n/**\\n * @dev Library for reading and writing value-types to specific transient storage slots.\\n *\\n * Transient slots are often used to store temporary values that are removed after the current transaction.\\n * This library helps with reading and writing to such slots without the need for inline assembly.\\n *\\n * * Example reading and writing values using transient storage:\\n * ```solidity\\n * contract Lock {\\n * using TransientSlot for *;\\n *\\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\\n *\\n * modifier locked() {\\n * require(!_LOCK_SLOT.asBoolean().tload());\\n *\\n * _LOCK_SLOT.asBoolean().tstore(true);\\n * _;\\n * _LOCK_SLOT.asBoolean().tstore(false);\\n * }\\n * }\\n * ```\\n *\\n * TIP: Consider using this library along with {SlotDerivation}.\\n */\\nlibrary TransientSlot {\\n /**\\n * @dev UDVT that represent a slot holding a address.\\n */\\n type AddressSlot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a AddressSlot.\\n */\\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\\n return AddressSlot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a bool.\\n */\\n type BooleanSlot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a BooleanSlot.\\n */\\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\\n return BooleanSlot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a bytes32.\\n */\\n type Bytes32Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Bytes32Slot.\\n */\\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\\n return Bytes32Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a uint256.\\n */\\n type Uint256Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Uint256Slot.\\n */\\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\\n return Uint256Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev UDVT that represent a slot holding a int256.\\n */\\n type Int256Slot is bytes32;\\n\\n /**\\n * @dev Cast an arbitrary slot to a Int256Slot.\\n */\\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\\n return Int256Slot.wrap(slot);\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(AddressSlot slot) internal view returns (address value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(AddressSlot slot, address value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(BooleanSlot slot) internal view returns (bool value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(BooleanSlot slot, bool value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Bytes32Slot slot, bytes32 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Uint256Slot slot, uint256 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n\\n /**\\n * @dev Load the value held at location `slot` in transient storage.\\n */\\n function tload(Int256Slot slot) internal view returns (int256 value) {\\n assembly (\\\"memory-safe\\\") {\\n value := tload(slot)\\n }\\n }\\n\\n /**\\n * @dev Store `value` at location `slot` in transient storage.\\n */\\n function tstore(Int256Slot slot, int256 value) internal {\\n assembly (\\\"memory-safe\\\") {\\n tstore(slot, value)\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9ce486f12ba619221439564671d06e5d389b7ac1c72f18d0b08a1e26368a2765\",\"license\":\"MIT\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b50611a838061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106102ff575f3560e01c80639254f5e511610195578063c7ee005e116100e4578063e0f6123d1161009e578063e875544611610079578063e8755446146107ee578063f445d703146107f7578063f851a44014610824578063fa6331d814610836575f80fd5b8063e0f6123d14610782578063e37d4b79146107a4578063e85a2960146107db575f80fd5b8063c7ee005e14610717578063d3270f991461072a578063d463654c1461073d578063d7c46d2d14610744578063dce154491461075c578063dcfbc0c71461076f575f80fd5b8063b8324c7c1161014f578063bec04f721161012a578063bec04f72146106bc578063bf32442d146106c5578063c5b4db55146106d6578063c5f956af14610704575f80fd5b8063b8324c7c1461062f578063bb82aa5e1461068a578063bbb8864a1461069d575f80fd5b80639254f5e5146105b857806394b2294b146105cb57806396c99064146105d45780639bb27d62146105f6578063a657e57914610609578063b2eafc391461061c575f80fd5b80634d99c77611610251578063737690991161020b5780637dc0d1d0116101e65780637dc0d1d0146105575780637fb8e8cd1461056a5780638a7dc165146105775780638c1ac18a14610596575f80fd5b806373769099146104f257806376551383146105325780637d172bd514610544575f80fd5b80634d99c77614610487578063517aa0c71461049a57806352d84d1e146104a25780635544ed9c146104b55780635dd3fc9d146104ca578063719f701b146104e9575f80fd5b806324a3d622116102bc5780634088c73e116102975780634088c73e1461041e57806341a18d2c1461042b578063425fad58146104555780634a58443214610468575f80fd5b806324a3d622146103d957806326782247146103ec5780632bc7e29e146103ff575f80fd5b806302c3bcbb1461030357806304ef9d581461033557806308e0225c1461033e5780630db4b4e51461036857806310b983381461037157806321af4569146103ae575b5f80fd5b6103226103113660046113d6565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61032260225481565b61032261034c3660046113f8565b601360209081525f928352604080842090915290825290205481565b610322601d5481565b61039e61037f3660046113f8565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161032c565b601e546103c1906001600160a01b031681565b6040516001600160a01b03909116815260200161032c565b600a546103c1906001600160a01b031681565b6001546103c1906001600160a01b031681565b61032261040d3660046113d6565b60166020525f908152604090205481565b60185461039e9060ff1681565b6103226104393660046113f8565b601260209081525f928352604080842090915290825290205481565b60185461039e9062010000900460ff1681565b6103226104763660046113d6565b601f6020525f908152604090205481565b61032261049536600461144a565b61083f565b61032260c881565b6103c16104b0366004611464565b610860565b6104c86104c33660046115bb565b610888565b005b6103226104d83660046113d6565b602b6020525f908152604090205481565b610322601c5481565b61051a6105003660046113d6565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161032c565b60185461039e90610100900460ff1681565b601b546103c1906001600160a01b031681565b6004546103c1906001600160a01b031681565b60395461039e9060ff1681565b6103226105853660046113d6565b60146020525f908152604090205481565b61039e6105a43660046113d6565b602d6020525f908152604090205460ff1681565b6015546103c1906001600160a01b031681565b61032260075481565b6105e76105e23660046116c0565b610b7a565b60405161032c93929190611707565b6025546103c1906001600160a01b031681565b60375461051a906001600160601b031681565b6020546103c1906001600160a01b031681565b61066661063d3660046113d6565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161032c565b6002546103c1906001600160a01b031681565b6103226106ab3660046113d6565b602a6020525f908152604090205481565b61032260175481565b6033546001600160a01b03166103c1565b6106ec6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b03909116815260200161032c565b6021546103c1906001600160a01b031681565b6031546103c1906001600160a01b031681565b6026546103c1906001600160a01b031681565b61051a5f81565b6039546103c19061010090046001600160a01b031681565b6103c161076a366004611730565b610c27565b6003546103c1906001600160a01b031681565b61039e6107903660046113d6565b60386020525f908152604090205460ff1681565b6106666107b23660046113d6565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61039e6107e936600461175a565b610c5b565b61032260055481565b61039e6108053660046113f8565b603260209081525f928352604080842090915290825290205460ff1681565b5f546103c1906001600160a01b031681565b610322601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d818154811061086f575f80fd5b5f918252602090912001546001600160a01b0316905081565b610890610c9f565b60395460ff16156108b4576040516323118a8360e01b815260040160405180910390fd5b6108bd85610d0e565b82515f8181036108e05760405163bd96af5b60e01b815260040160405180910390fd5b60c88211156109115760405163d2f1924360e01b81526004810183905260c860248201526044015b60405180910390fd5b835182146109325760405163aa6eb14560e01b815260040160405180910390fd5b5f5b82811015610a845761095e86828151811061095157610951611789565b6020026020010151610d5f565b805490925060ff166109ad5785818151811061097c5761097c611789565b6020026020010151604051635a9a1eb960e11b815260040161090891906001600160a01b0391909116815260200190565b8581815181106109bf576109bf611789565b60200260200101516001600160a01b031663ae3fcb1f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a02573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a2691906117ac565b610a4357604051630a3fad8360e01b815260040160405180910390fd5b848181518110610a5557610a55611789565b60200260200101515f03610a7c5760405163162908e360e11b815260040160405180910390fd5b600101610934565b50610a8e86610d0e565b335f9081526038602052604090205460ff16610abf576040516319d14ecf60e01b8152336004820152602401610908565b336001600160a01b03881614801590610afb57506001600160a01b0387165f908152602c6020908152604080832033845290915290205460ff16155b15610b19576040516337248ad960e01b815260040160405180910390fd5b610b268787878787610d81565b856001600160a01b03167f785e5057f6e5f2e298f8dce2755a6ef29f9dd8a0f82a8b5cad101ea5ef803f048686604051610b61929190611837565b60405180910390a25050610b73610e5c565b5050505050565b60366020525f9081526040902080548190610b9490611864565b80601f0160208091040260200160405190810160405280929190818152602001828054610bc090611864565b8015610c0b5780601f10610be257610100808354040283529160200191610c0b565b820191905f5260205f20905b815481529060010190602001808311610bee57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6008602052815f5260405f208181548110610c40575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610c8557610c8561189c565b815260208101919091526040015f205460ff169392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15610cdf57604051633ee5aeb560e01b815260040160405180910390fd5b610d0c60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90610e86565b565b6001600160a01b038116610d5c5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610908565b50565b5f60095f610d6d5f8561083f565b81526020019081526020015f209050919050565b604080518082019091526060808252602082015283518067ffffffffffffffff811115610db057610db061147b565b604051908082528060200260200182016040528015610dd9578160200160208202803683370190505b5082528067ffffffffffffffff811115610df557610df561147b565b604051908082528060200260200182016040528015610e1e578160200160208202803683370190505b506020830152610e3086868685610e8d565b5f610e4288888888875f01518961102d565b9050610e528888888885886110d7565b5050505050505050565b610d0c5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00610d06565b80825d5050565b82515f5b8181101561102557848181518110610eab57610eab611789565b60200260200101516001600160a01b03166371507cd5858381518110610ed357610ed3611789565b60200260200101516040518263ffffffff1660e01b8152600401610ef991815260200190565b6040805180830381865afa158015610f13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3791906118b0565b8451805184908110610f4b57610f4b611789565b6020026020010185602001518481518110610f6857610f68611789565b6020026020010182815250828152505050848181518110610f8b57610f8b611789565b60200260200101516001600160a01b0316638d1f23d487868481518110610fb457610fb4611789565b60200260200101516040518363ffffffff1660e01b8152600401610fed9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b158015611004575f80fd5b505af1158015611016573d5f803e3d5ffd5b50505050806001019050610e91565b505050505050565b60605f80876001600160a01b031663fc08f9f6888888338e8a6040518763ffffffff1660e01b8152600401611067969594939291906118d2565b5f604051808303815f875af1158015611082573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110a99190810190611942565b91509150816110cb57604051635a3b2cbb60e11b815260040160405180910390fd5b98975050505050505050565b83515f5b81811015610e52576111768682815181106110f8576110f8611789565b6020026020010151898988858151811061111457611114611789565b602002602001015188868151811061112e5761112e611789565b6020026020010151885f0151878151811061114b5761114b611789565b60200260200101518960200151888151811061116957611169611789565b602002602001015161117e565b6001016110db565b5f61118983866119f5565b90505f818511611199578461119b565b815b9050838110156111c85760405163bcb60bf360e01b81526004810182905260248101859052604401610908565b60405163324235c960e11b81526001600160a01b0388811660048301526024820183905260448201869052606482018590525f91908b16906364846b92906084016020604051808303815f875af1158015611225573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112499190611a08565b90505f818411156112f65761125e8285611a1f565b6040516366ce8d7d60e01b81526001600160a01b038c81166004830152602482018390529192505f918d16906366ce8d7d906044016020604051808303815f875af11580156112af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d39190611a08565b905080156112f45760405163ab52b56f60e01b815260040160405180910390fd5b505b8a6001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611332573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113569190611a32565b6001600160a01b03168a6001600160a01b03168a6001600160a01b03167f499433c603d8d6db664daa76d7158679cc9f90c4c30723e29495a8c39302a17385856040516113ad929190918252602082015260400190565b60405180910390a45050505050505050505050565b6001600160a01b0381168114610d5c575f80fd5b5f602082840312156113e6575f80fd5b81356113f1816113c2565b9392505050565b5f8060408385031215611409575f80fd5b8235611414816113c2565b91506020830135611424816113c2565b809150509250929050565b80356001600160601b0381168114611445575f80fd5b919050565b5f806040838503121561145b575f80fd5b6114148361142f565b5f60208284031215611474575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114b8576114b861147b565b604052919050565b5f67ffffffffffffffff8211156114d9576114d961147b565b5060051b60200190565b5f82601f8301126114f2575f80fd5b81356020611507611502836114c0565b61148f565b8083825260208201915060208460051b870101935086841115611528575f80fd5b602086015b84811015611544578035835291830191830161152d565b509695505050505050565b5f82601f83011261155e575f80fd5b813567ffffffffffffffff8111156115785761157861147b565b61158b601f8201601f191660200161148f565b81815284602083860101111561159f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a086880312156115cf575f80fd5b85356115da816113c2565b94506020868101356115eb816113c2565b9450604087013567ffffffffffffffff80821115611607575f80fd5b818901915089601f83011261161a575f80fd5b8135611628611502826114c0565b81815260059190911b8301840190848101908c831115611646575f80fd5b938501935b8285101561166d57843561165e816113c2565b8252938501939085019061164b565b975050506060890135925080831115611684575f80fd5b6116908a848b016114e3565b945060808901359250808311156116a5575f80fd5b50506116b38882890161154f565b9150509295509295909350565b5f602082840312156116d0575f80fd5b6113f18261142f565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61171960608301866116d9565b931515602083015250901515604090910152919050565b5f8060408385031215611741575f80fd5b823561174c816113c2565b946020939093013593505050565b5f806040838503121561176b575f80fd5b8235611776816113c2565b9150602083013560098110611424575f80fd5b634e487b7160e01b5f52603260045260245ffd5b80518015158114611445575f80fd5b5f602082840312156117bc575f80fd5b6113f18261179d565b5f815180845260208085019450602084015f5b838110156117fd5781516001600160a01b0316875295820195908201906001016117d8565b509495945050505050565b5f815180845260208085019450602084015f5b838110156117fd5781518752958201959082019060010161181b565b604081525f61184960408301856117c5565b828103602084015261185b8185611808565b95945050505050565b600181811c9082168061187857607f821691505b60208210810361189657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156118c1575f80fd5b505080516020909101519092909150565b60c081525f6118e460c08301896117c5565b82810360208401526118f68189611808565b9050828103604084015261190a8188611808565b6001600160a01b0387811660608601528616608085015283810360a0850152905061193581856116d9565b9998505050505050505050565b5f8060408385031215611953575f80fd5b61195c8361179d565b915060208084015167ffffffffffffffff811115611978575f80fd5b8401601f81018613611988575f80fd5b8051611996611502826114c0565b81815260059190911b820183019083810190888311156119b4575f80fd5b928401925b828410156119d2578351825292840192908401906119b9565b80955050505050509250929050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561085a5761085a6119e1565b5f60208284031215611a18575f80fd5b5051919050565b8181038181111561085a5761085a6119e1565b5f60208284031215611a42575f80fd5b81516113f1816113c256fea264697066735822122059fa1e9920e5a07a45214aeb0caee813135dfa60a1279a4befe3f8462d7d6fb464736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102ff575f3560e01c80639254f5e511610195578063c7ee005e116100e4578063e0f6123d1161009e578063e875544611610079578063e8755446146107ee578063f445d703146107f7578063f851a44014610824578063fa6331d814610836575f80fd5b8063e0f6123d14610782578063e37d4b79146107a4578063e85a2960146107db575f80fd5b8063c7ee005e14610717578063d3270f991461072a578063d463654c1461073d578063d7c46d2d14610744578063dce154491461075c578063dcfbc0c71461076f575f80fd5b8063b8324c7c1161014f578063bec04f721161012a578063bec04f72146106bc578063bf32442d146106c5578063c5b4db55146106d6578063c5f956af14610704575f80fd5b8063b8324c7c1461062f578063bb82aa5e1461068a578063bbb8864a1461069d575f80fd5b80639254f5e5146105b857806394b2294b146105cb57806396c99064146105d45780639bb27d62146105f6578063a657e57914610609578063b2eafc391461061c575f80fd5b80634d99c77611610251578063737690991161020b5780637dc0d1d0116101e65780637dc0d1d0146105575780637fb8e8cd1461056a5780638a7dc165146105775780638c1ac18a14610596575f80fd5b806373769099146104f257806376551383146105325780637d172bd514610544575f80fd5b80634d99c77614610487578063517aa0c71461049a57806352d84d1e146104a25780635544ed9c146104b55780635dd3fc9d146104ca578063719f701b146104e9575f80fd5b806324a3d622116102bc5780634088c73e116102975780634088c73e1461041e57806341a18d2c1461042b578063425fad58146104555780634a58443214610468575f80fd5b806324a3d622146103d957806326782247146103ec5780632bc7e29e146103ff575f80fd5b806302c3bcbb1461030357806304ef9d581461033557806308e0225c1461033e5780630db4b4e51461036857806310b983381461037157806321af4569146103ae575b5f80fd5b6103226103113660046113d6565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61032260225481565b61032261034c3660046113f8565b601360209081525f928352604080842090915290825290205481565b610322601d5481565b61039e61037f3660046113f8565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161032c565b601e546103c1906001600160a01b031681565b6040516001600160a01b03909116815260200161032c565b600a546103c1906001600160a01b031681565b6001546103c1906001600160a01b031681565b61032261040d3660046113d6565b60166020525f908152604090205481565b60185461039e9060ff1681565b6103226104393660046113f8565b601260209081525f928352604080842090915290825290205481565b60185461039e9062010000900460ff1681565b6103226104763660046113d6565b601f6020525f908152604090205481565b61032261049536600461144a565b61083f565b61032260c881565b6103c16104b0366004611464565b610860565b6104c86104c33660046115bb565b610888565b005b6103226104d83660046113d6565b602b6020525f908152604090205481565b610322601c5481565b61051a6105003660046113d6565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161032c565b60185461039e90610100900460ff1681565b601b546103c1906001600160a01b031681565b6004546103c1906001600160a01b031681565b60395461039e9060ff1681565b6103226105853660046113d6565b60146020525f908152604090205481565b61039e6105a43660046113d6565b602d6020525f908152604090205460ff1681565b6015546103c1906001600160a01b031681565b61032260075481565b6105e76105e23660046116c0565b610b7a565b60405161032c93929190611707565b6025546103c1906001600160a01b031681565b60375461051a906001600160601b031681565b6020546103c1906001600160a01b031681565b61066661063d3660046113d6565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161032c565b6002546103c1906001600160a01b031681565b6103226106ab3660046113d6565b602a6020525f908152604090205481565b61032260175481565b6033546001600160a01b03166103c1565b6106ec6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b03909116815260200161032c565b6021546103c1906001600160a01b031681565b6031546103c1906001600160a01b031681565b6026546103c1906001600160a01b031681565b61051a5f81565b6039546103c19061010090046001600160a01b031681565b6103c161076a366004611730565b610c27565b6003546103c1906001600160a01b031681565b61039e6107903660046113d6565b60386020525f908152604090205460ff1681565b6106666107b23660046113d6565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61039e6107e936600461175a565b610c5b565b61032260055481565b61039e6108053660046113f8565b603260209081525f928352604080842090915290825290205460ff1681565b5f546103c1906001600160a01b031681565b610322601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d818154811061086f575f80fd5b5f918252602090912001546001600160a01b0316905081565b610890610c9f565b60395460ff16156108b4576040516323118a8360e01b815260040160405180910390fd5b6108bd85610d0e565b82515f8181036108e05760405163bd96af5b60e01b815260040160405180910390fd5b60c88211156109115760405163d2f1924360e01b81526004810183905260c860248201526044015b60405180910390fd5b835182146109325760405163aa6eb14560e01b815260040160405180910390fd5b5f5b82811015610a845761095e86828151811061095157610951611789565b6020026020010151610d5f565b805490925060ff166109ad5785818151811061097c5761097c611789565b6020026020010151604051635a9a1eb960e11b815260040161090891906001600160a01b0391909116815260200190565b8581815181106109bf576109bf611789565b60200260200101516001600160a01b031663ae3fcb1f6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a02573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a2691906117ac565b610a4357604051630a3fad8360e01b815260040160405180910390fd5b848181518110610a5557610a55611789565b60200260200101515f03610a7c5760405163162908e360e11b815260040160405180910390fd5b600101610934565b50610a8e86610d0e565b335f9081526038602052604090205460ff16610abf576040516319d14ecf60e01b8152336004820152602401610908565b336001600160a01b03881614801590610afb57506001600160a01b0387165f908152602c6020908152604080832033845290915290205460ff16155b15610b19576040516337248ad960e01b815260040160405180910390fd5b610b268787878787610d81565b856001600160a01b03167f785e5057f6e5f2e298f8dce2755a6ef29f9dd8a0f82a8b5cad101ea5ef803f048686604051610b61929190611837565b60405180910390a25050610b73610e5c565b5050505050565b60366020525f9081526040902080548190610b9490611864565b80601f0160208091040260200160405190810160405280929190818152602001828054610bc090611864565b8015610c0b5780601f10610be257610100808354040283529160200191610c0b565b820191905f5260205f20905b815481529060010190602001808311610bee57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6008602052815f5260405f208181548110610c40575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610c8557610c8561189c565b815260208101919091526040015f205460ff169392505050565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c15610cdf57604051633ee5aeb560e01b815260040160405180910390fd5b610d0c60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005b90610e86565b565b6001600160a01b038116610d5c5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610908565b50565b5f60095f610d6d5f8561083f565b81526020019081526020015f209050919050565b604080518082019091526060808252602082015283518067ffffffffffffffff811115610db057610db061147b565b604051908082528060200260200182016040528015610dd9578160200160208202803683370190505b5082528067ffffffffffffffff811115610df557610df561147b565b604051908082528060200260200182016040528015610e1e578160200160208202803683370190505b506020830152610e3086868685610e8d565b5f610e4288888888875f01518961102d565b9050610e528888888885886110d7565b5050505050505050565b610d0c5f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00610d06565b80825d5050565b82515f5b8181101561102557848181518110610eab57610eab611789565b60200260200101516001600160a01b03166371507cd5858381518110610ed357610ed3611789565b60200260200101516040518263ffffffff1660e01b8152600401610ef991815260200190565b6040805180830381865afa158015610f13573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3791906118b0565b8451805184908110610f4b57610f4b611789565b6020026020010185602001518481518110610f6857610f68611789565b6020026020010182815250828152505050848181518110610f8b57610f8b611789565b60200260200101516001600160a01b0316638d1f23d487868481518110610fb457610fb4611789565b60200260200101516040518363ffffffff1660e01b8152600401610fed9291906001600160a01b03929092168252602082015260400190565b5f604051808303815f87803b158015611004575f80fd5b505af1158015611016573d5f803e3d5ffd5b50505050806001019050610e91565b505050505050565b60605f80876001600160a01b031663fc08f9f6888888338e8a6040518763ffffffff1660e01b8152600401611067969594939291906118d2565b5f604051808303815f875af1158015611082573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526110a99190810190611942565b91509150816110cb57604051635a3b2cbb60e11b815260040160405180910390fd5b98975050505050505050565b83515f5b81811015610e52576111768682815181106110f8576110f8611789565b6020026020010151898988858151811061111457611114611789565b602002602001015188868151811061112e5761112e611789565b6020026020010151885f0151878151811061114b5761114b611789565b60200260200101518960200151888151811061116957611169611789565b602002602001015161117e565b6001016110db565b5f61118983866119f5565b90505f818511611199578461119b565b815b9050838110156111c85760405163bcb60bf360e01b81526004810182905260248101859052604401610908565b60405163324235c960e11b81526001600160a01b0388811660048301526024820183905260448201869052606482018590525f91908b16906364846b92906084016020604051808303815f875af1158015611225573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112499190611a08565b90505f818411156112f65761125e8285611a1f565b6040516366ce8d7d60e01b81526001600160a01b038c81166004830152602482018390529192505f918d16906366ce8d7d906044016020604051808303815f875af11580156112af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112d39190611a08565b905080156112f45760405163ab52b56f60e01b815260040160405180910390fd5b505b8a6001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015611332573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113569190611a32565b6001600160a01b03168a6001600160a01b03168a6001600160a01b03167f499433c603d8d6db664daa76d7158679cc9f90c4c30723e29495a8c39302a17385856040516113ad929190918252602082015260400190565b60405180910390a45050505050505050505050565b6001600160a01b0381168114610d5c575f80fd5b5f602082840312156113e6575f80fd5b81356113f1816113c2565b9392505050565b5f8060408385031215611409575f80fd5b8235611414816113c2565b91506020830135611424816113c2565b809150509250929050565b80356001600160601b0381168114611445575f80fd5b919050565b5f806040838503121561145b575f80fd5b6114148361142f565b5f60208284031215611474575f80fd5b5035919050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156114b8576114b861147b565b604052919050565b5f67ffffffffffffffff8211156114d9576114d961147b565b5060051b60200190565b5f82601f8301126114f2575f80fd5b81356020611507611502836114c0565b61148f565b8083825260208201915060208460051b870101935086841115611528575f80fd5b602086015b84811015611544578035835291830191830161152d565b509695505050505050565b5f82601f83011261155e575f80fd5b813567ffffffffffffffff8111156115785761157861147b565b61158b601f8201601f191660200161148f565b81815284602083860101111561159f575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f60a086880312156115cf575f80fd5b85356115da816113c2565b94506020868101356115eb816113c2565b9450604087013567ffffffffffffffff80821115611607575f80fd5b818901915089601f83011261161a575f80fd5b8135611628611502826114c0565b81815260059190911b8301840190848101908c831115611646575f80fd5b938501935b8285101561166d57843561165e816113c2565b8252938501939085019061164b565b975050506060890135925080831115611684575f80fd5b6116908a848b016114e3565b945060808901359250808311156116a5575f80fd5b50506116b38882890161154f565b9150509295509295909350565b5f602082840312156116d0575f80fd5b6113f18261142f565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61171960608301866116d9565b931515602083015250901515604090910152919050565b5f8060408385031215611741575f80fd5b823561174c816113c2565b946020939093013593505050565b5f806040838503121561176b575f80fd5b8235611776816113c2565b9150602083013560098110611424575f80fd5b634e487b7160e01b5f52603260045260245ffd5b80518015158114611445575f80fd5b5f602082840312156117bc575f80fd5b6113f18261179d565b5f815180845260208085019450602084015f5b838110156117fd5781516001600160a01b0316875295820195908201906001016117d8565b509495945050505050565b5f815180845260208085019450602084015f5b838110156117fd5781518752958201959082019060010161181b565b604081525f61184960408301856117c5565b828103602084015261185b8185611808565b95945050505050565b600181811c9082168061187857607f821691505b60208210810361189657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156118c1575f80fd5b505080516020909101519092909150565b60c081525f6118e460c08301896117c5565b82810360208401526118f68189611808565b9050828103604084015261190a8188611808565b6001600160a01b0387811660608601528616608085015283810360a0850152905061193581856116d9565b9998505050505050505050565b5f8060408385031215611953575f80fd5b61195c8361179d565b915060208084015167ffffffffffffffff811115611978575f80fd5b8401601f81018613611988575f80fd5b8051611996611502826114c0565b81815260059190911b820183019083810190888311156119b4575f80fd5b928401925b828410156119d2578351825292840192908401906119b9565b80955050505050509250929050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561085a5761085a6119e1565b5f60208284031215611a18575f80fd5b5051919050565b8181038181111561085a5761085a6119e1565b5f60208284031215611a42575f80fd5b81516113f1816113c256fea264697066735822122059fa1e9920e5a07a45214aeb0caee813135dfa60a1279a4befe3f8462d7d6fb464736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This contract implements flash loan functionality allowing users to borrow assets temporarily within a single transaction. Users can borrow multiple assets simultaneously and have the flexibility to repay partially, with unpaid balances automatically converted to debt positions. The contract supports protocol fee collection and integrates with the Venus lending protocol.", @@ -1417,6 +1430,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "executeFlashLoan(address,address,address[],uint256[],bytes)": { "notice": "Executes a flashLoan operation with the requested assets." }, @@ -1523,7 +1539,7 @@ "storageLayout": { "storage": [ { - "astId": 1652, + "astId": 9780, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "admin", "offset": 0, @@ -1531,7 +1547,7 @@ "type": "t_address" }, { - "astId": 1655, + "astId": 9783, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "pendingAdmin", "offset": 0, @@ -1539,7 +1555,7 @@ "type": "t_address" }, { - "astId": 1658, + "astId": 9786, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "comptrollerImplementation", "offset": 0, @@ -1547,7 +1563,7 @@ "type": "t_address" }, { - "astId": 1661, + "astId": 9789, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -1555,15 +1571,15 @@ "type": "t_address" }, { - "astId": 1668, + "astId": 9796, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)967" + "type": "t_contract(ResilientOracleInterface)8467" }, { - "astId": 1671, + "astId": 9799, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "closeFactorMantissa", "offset": 0, @@ -1571,7 +1587,7 @@ "type": "t_uint256" }, { - "astId": 1674, + "astId": 9802, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -1579,7 +1595,7 @@ "type": "t_uint256" }, { - "astId": 1677, + "astId": 9805, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "maxAssets", "offset": 0, @@ -1587,23 +1603,23 @@ "type": "t_uint256" }, { - "astId": 1684, + "astId": 9812, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)17915)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)" }, { - "astId": 1718, + "astId": 9846, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11388,t_struct(Market)1711_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)" }, { - "astId": 1721, + "astId": 9849, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "pauseGuardian", "offset": 0, @@ -1611,7 +1627,7 @@ "type": "t_address" }, { - "astId": 1724, + "astId": 9852, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -1619,7 +1635,7 @@ "type": "t_bool" }, { - "astId": 1727, + "astId": 9855, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -1627,7 +1643,7 @@ "type": "t_bool" }, { - "astId": 1730, + "astId": 9858, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "transferGuardianPaused", "offset": 22, @@ -1635,7 +1651,7 @@ "type": "t_bool" }, { - "astId": 1733, + "astId": 9861, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -1643,7 +1659,7 @@ "type": "t_bool" }, { - "astId": 1738, + "astId": 9866, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "mintGuardianPaused", "offset": 0, @@ -1651,7 +1667,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1743, + "astId": 9871, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -1659,15 +1675,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1755, + "astId": 9883, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)17915)dyn_storage" + "type": "t_array(t_contract(VToken)58633)dyn_storage" }, { - "astId": 1758, + "astId": 9886, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusRate", "offset": 0, @@ -1675,7 +1691,7 @@ "type": "t_uint256" }, { - "astId": 1763, + "astId": 9891, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusSpeeds", "offset": 0, @@ -1683,23 +1699,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1769, + "astId": 9897, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1775, + "astId": 9903, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1782, + "astId": 9910, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusSupplierIndex", "offset": 0, @@ -1707,7 +1723,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1789, + "astId": 9917, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -1715,7 +1731,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1794, + "astId": 9922, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusAccrued", "offset": 0, @@ -1723,15 +1739,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1798, + "astId": 9926, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)11813" + "type": "t_contract(VAIControllerInterface)51683" }, { - "astId": 1803, + "astId": 9931, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "mintedVAIs", "offset": 0, @@ -1739,7 +1755,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1806, + "astId": 9934, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "vaiMintRate", "offset": 0, @@ -1747,7 +1763,7 @@ "type": "t_uint256" }, { - "astId": 1809, + "astId": 9937, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -1755,7 +1771,7 @@ "type": "t_bool" }, { - "astId": 1811, + "astId": 9939, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -1763,7 +1779,7 @@ "type": "t_bool" }, { - "astId": 1814, + "astId": 9942, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "protocolPaused", "offset": 2, @@ -1771,7 +1787,7 @@ "type": "t_bool" }, { - "astId": 1817, + "astId": 9945, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusVAIRate", "offset": 0, @@ -1779,7 +1795,7 @@ "type": "t_uint256" }, { - "astId": 1823, + "astId": 9951, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -1787,7 +1803,7 @@ "type": "t_uint256" }, { - "astId": 1825, + "astId": 9953, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "vaiVaultAddress", "offset": 0, @@ -1795,7 +1811,7 @@ "type": "t_address" }, { - "astId": 1827, + "astId": 9955, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "releaseStartBlock", "offset": 0, @@ -1803,7 +1819,7 @@ "type": "t_uint256" }, { - "astId": 1829, + "astId": 9957, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "minReleaseAmount", "offset": 0, @@ -1811,7 +1827,7 @@ "type": "t_uint256" }, { - "astId": 1835, + "astId": 9963, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "borrowCapGuardian", "offset": 0, @@ -1819,7 +1835,7 @@ "type": "t_address" }, { - "astId": 1840, + "astId": 9968, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "borrowCaps", "offset": 0, @@ -1827,7 +1843,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1846, + "astId": 9974, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "treasuryGuardian", "offset": 0, @@ -1835,7 +1851,7 @@ "type": "t_address" }, { - "astId": 1849, + "astId": 9977, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "treasuryAddress", "offset": 0, @@ -1843,7 +1859,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9980, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "treasuryPercent", "offset": 0, @@ -1851,7 +1867,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9988, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -1859,7 +1875,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1865, + "astId": 9993, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "lastContributorBlock", "offset": 0, @@ -1867,7 +1883,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1870, + "astId": 9998, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "liquidatorContract", "offset": 0, @@ -1875,15 +1891,15 @@ "type": "t_address" }, { - "astId": 1876, + "astId": 10004, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1635" + "type": "t_contract(ComptrollerLensInterface)9761" }, { - "astId": 1884, + "astId": 10012, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "supplyCaps", "offset": 0, @@ -1891,7 +1907,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 10018, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "accessControl", "offset": 0, @@ -1899,7 +1915,7 @@ "type": "t_address" }, { - "astId": 1897, + "astId": 10025, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_actionPaused", "offset": 0, @@ -1907,7 +1923,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1905, + "astId": 10033, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -1915,7 +1931,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1910, + "astId": 10038, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -1923,7 +1939,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1920, + "astId": 10048, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "approvedDelegates", "offset": 0, @@ -1931,7 +1947,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1928, + "astId": 10056, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -1939,23 +1955,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1947, + "astId": 10075, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1936_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)" }, { - "astId": 1952, + "astId": 10080, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1942_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)" }, { - "astId": 1955, + "astId": 10083, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "_facetAddresses", "offset": 0, @@ -1963,15 +1979,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1962, + "astId": 10090, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)11746" + "type": "t_contract(IPrime)42902" }, { - "astId": 1972, + "astId": 10100, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -1979,7 +1995,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1978, + "astId": 10106, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "xvs", "offset": 0, @@ -1987,7 +2003,7 @@ "type": "t_address" }, { - "astId": 1981, + "astId": 10109, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "xvsVToken", "offset": 0, @@ -1995,7 +2011,7 @@ "type": "t_address" }, { - "astId": 2003, + "astId": 10131, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "userPoolId", "offset": 0, @@ -2003,15 +2019,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2009, + "astId": 10137, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)1998_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)10126_storage)" }, { - "astId": 2012, + "astId": 10140, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "lastPoolId", "offset": 0, @@ -2019,7 +2035,7 @@ "type": "t_uint96" }, { - "astId": 2020, + "astId": 10148, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -2027,12 +2043,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2023, + "astId": 10151, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 10158, + "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)8437" } ], "types": { @@ -2053,8 +2077,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)17915)dyn_storage": { - "base": "t_contract(VToken)17915", + "t_array(t_contract(VToken)58633)dyn_storage": { + "base": "t_contract(VToken)58633", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -2069,37 +2093,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1635": { + "t_contract(ComptrollerLensInterface)9761": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)11746": { + "t_contract(IDeviationBoundedOracle)8437": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)42902": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)967": { + "t_contract(ResilientOracleInterface)8467": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)11813": { + "t_contract(VAIControllerInterface)51683": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)17915": { + "t_contract(VToken)58633": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)17915)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)17915)dyn_storage" + "value": "t_array(t_contract(VToken)58633)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -2129,19 +2158,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1942_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1942_storage" + "value": "t_struct(FacetFunctionSelectors)10070_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1750_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1750_storage" + "value": "t_struct(VenusMarketState)9878_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2157,12 +2186,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1936_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1936_storage" + "value": "t_struct(FacetAddressAndPosition)10064_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -2171,31 +2200,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)1998_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)10126_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)1998_storage" + "value": "t_struct(PoolData)10126_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11388,t_struct(Market)1711_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11388", + "key": "t_userDefinedValueType(PoolMarketId)19777", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1711_storage" + "value": "t_struct(Market)9839_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1936_storage": { + "t_struct(FacetAddressAndPosition)10064_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1933, + "astId": 10061, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "facetAddress", "offset": 0, @@ -2203,7 +2232,7 @@ "type": "t_address" }, { - "astId": 1935, + "astId": 10063, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "functionSelectorPosition", "offset": 20, @@ -2213,12 +2242,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1942_storage": { + "t_struct(FacetFunctionSelectors)10070_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1939, + "astId": 10067, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "functionSelectors", "offset": 0, @@ -2226,7 +2255,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1941, + "astId": 10069, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "facetAddressPosition", "offset": 0, @@ -2236,12 +2265,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1711_storage": { + "t_struct(Market)9839_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1687, + "astId": 9815, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isListed", "offset": 0, @@ -2249,7 +2278,7 @@ "type": "t_bool" }, { - "astId": 1690, + "astId": 9818, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -2257,7 +2286,7 @@ "type": "t_uint256" }, { - "astId": 1695, + "astId": 9823, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "accountMembership", "offset": 0, @@ -2265,7 +2294,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1698, + "astId": 9826, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isVenus", "offset": 0, @@ -2273,7 +2302,7 @@ "type": "t_bool" }, { - "astId": 1701, + "astId": 9829, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -2281,7 +2310,7 @@ "type": "t_uint256" }, { - "astId": 1704, + "astId": 9832, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -2289,7 +2318,7 @@ "type": "t_uint256" }, { - "astId": 1707, + "astId": 9835, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "poolId", "offset": 0, @@ -2297,7 +2326,7 @@ "type": "t_uint96" }, { - "astId": 1710, + "astId": 9838, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isBorrowAllowed", "offset": 12, @@ -2307,12 +2336,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)1998_storage": { + "t_struct(PoolData)10126_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 1987, + "astId": 10115, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "label", "offset": 0, @@ -2320,7 +2349,7 @@ "type": "t_string_storage" }, { - "astId": 1991, + "astId": 10119, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "vTokens", "offset": 0, @@ -2328,7 +2357,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1994, + "astId": 10122, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "isActive", "offset": 0, @@ -2336,7 +2365,7 @@ "type": "t_bool" }, { - "astId": 1997, + "astId": 10125, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -2346,12 +2375,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1750_storage": { + "t_struct(VenusMarketState)9878_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1746, + "astId": 9874, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "index", "offset": 0, @@ -2359,7 +2388,7 @@ "type": "t_uint224" }, { - "astId": 1749, + "astId": 9877, "contract": "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol:FlashLoanFacet", "label": "block", "offset": 28, @@ -2389,7 +2418,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11388": { + "t_userDefinedValueType(PoolMarketId)19777": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bsctestnet/MarketFacet.json b/deployments/bsctestnet/MarketFacet.json index a16b85c85..e6f870e96 100644 --- a/deployments/bsctestnet/MarketFacet.json +++ b/deployments/bsctestnet/MarketFacet.json @@ -1,5 +1,5 @@ { - "address": "0x8e0e15C99Ab0985cB39B2FE36532E5692730eBA9", + "address": "0xE160Afd62cAE8FCB16F6b702B325883dd80358d4", "abi": [ { "inputs": [], @@ -712,6 +712,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1889,28 +1902,28 @@ "type": "function" } ], - "transactionHash": "0xb90a8ea34e8c8b67714e0d1e332f4f6311289825aa4df31c26b6fec5c8c4e3be", + "transactionHash": "0x09da44a91af4b41a05d6b7c19497fc75787c082711d569f44ea4b14e9a5ec5b3", "receipt": { "to": null, - "from": "0x9cc6F5f16498fCEEf4D00A350Bd8F8921D304Dc9", - "contractAddress": "0x8e0e15C99Ab0985cB39B2FE36532E5692730eBA9", - "transactionIndex": 1100, - "gasUsed": "3157624", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0xE160Afd62cAE8FCB16F6b702B325883dd80358d4", + "transactionIndex": 0, + "gasUsed": "3228522", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xde0f65e6b476ba9f92001ad4cf9237b24feb2e2d897d5cd5d7c78c7a276975af", - "transactionHash": "0xb90a8ea34e8c8b67714e0d1e332f4f6311289825aa4df31c26b6fec5c8c4e3be", + "blockHash": "0xe56aa9278a2479636effd50c5d575b7f935cba0c6f4c66d91b1446790ad0d084", + "transactionHash": "0x09da44a91af4b41a05d6b7c19497fc75787c082711d569f44ea4b14e9a5ec5b3", "logs": [], - "blockNumber": 73653958, - "cumulativeGasUsed": "63249531", + "blockNumber": 102774076, + "cumulativeGasUsed": "3228522", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 1, - "solcInputHash": "34e3f00342319d109c5ecd417df3f3a4", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"DelegateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketUnlisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"PoolCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"PoolMarketInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"previousPoolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"newPoolId\",\"type\":\"uint96\"}],\"name\":\"PoolSelected\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96[]\",\"name\":\"poolIds\",\"type\":\"uint96[]\"},{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"addPoolMarkets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"createPool\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"enterMarketBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"enterPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getEffectiveLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"enum WeightFunction\",\"name\":\"weightingStrategy\",\"type\":\"uint8\"}],\"name\":\"getEffectiveLtvFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getLiquidationThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"getPoolVTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"targetPoolId\",\"type\":\"uint96\"}],\"name\":\"hasValidPoolBorrows\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"isMarketListed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateVAICalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isVenus\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"marketPoolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"isBorrowAllowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"poolMarkets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isVenus\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"marketPoolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"isBorrowAllowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"removePoolMarket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"unlistMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"updateDelegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the methods related to the market's management in the pool\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_supportMarket(address)\":{\"details\":\"Allows a privileged role to add and list markets to the Comptroller\",\"params\":{\"vToken\":\"The address of the vToken market to list in the Core Pool\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"addPoolMarkets(uint96[],address[])\":{\"custom:error\":\"ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.MarketNotListedInCorePool Reverts if the market is not listed in the core pool.MarketAlreadyListed Reverts if the given market is already listed in the specified pool.InactivePool Reverts if attempted to add markets to an inactive pool.\",\"custom:event\":\"PoolMarketInitialized Emitted after successfully initializing a market in a pool.\",\"params\":{\"poolIds\":\"Array of pool IDs.\",\"vTokens\":\"Array of market (vToken) addresses.\"}},\"checkMembership(address,address)\":{\"details\":\"Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools, all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\",\"params\":{\"account\":\"The address of the account to check\",\"vToken\":\"The vToken to check\"},\"returns\":{\"_0\":\"True if the account is in the asset, otherwise false\"}},\"createPool(string)\":{\"custom:error\":\"EmptyPoolLabel Reverts if the provided label is an empty string.\",\"custom:event\":\"PoolCreated Emitted after successfully creating a new pool.\",\"params\":{\"label\":\"name for the pool (must be non-empty).\"},\"returns\":{\"_0\":\"poolId The incremental unique identifier of the newly created pool.\"}},\"enterMarketBehalf(address,address)\":{\"custom:error\":\"NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\",\"details\":\"Only callable by the account itself or an approved delegate\",\"params\":{\"onBehalf\":\"The address of the account entering the market\",\"vToken\":\"The address of the vToken market to enable for the account\"},\"returns\":{\"_0\":\"uint256 indicating the result (0 = success, non-zero = failure)\"}},\"enterMarkets(address[])\":{\"params\":{\"vTokens\":\"The list of addresses of the vToken markets to be enabled\"},\"returns\":{\"_0\":\"Success indicator for whether each corresponding market was entered\"}},\"enterPool(uint96)\":{\"custom:error\":\"PoolDoesNotExist The specified pool ID does not exist.AlreadyInSelectedPool The user is already in the target pool.IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.LiquidityCheckFailed The user's liquidity is insufficient after switching pools.InactivePool The user is trying to enter inactive pool.\",\"custom:event\":\"PoolSelected Emitted after a successful pool switch.\",\"params\":{\"poolId\":\"The ID of the pool the user wants to enter.\"}},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow\",\"params\":{\"vTokenAddress\":\"The address of the asset to be removed\"},\"returns\":{\"_0\":\"Whether or not the account successfully exited the market\"}},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market\",\"returns\":{\"_0\":\"The list of market addresses\"}},\"getAssetsIn(address)\":{\"details\":\"Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools, all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\",\"params\":{\"account\":\"The address of the account to query\"},\"returns\":{\"_0\":\"assets A dynamic array of vToken markets the account has entered\"}},\"getCollateralFactor(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the collateral factor for\"},\"returns\":{\"_0\":\"The collateral factor for the vToken, scaled by 1e18\"}},\"getEffectiveLiquidationIncentive(address,address)\":{\"details\":\"The incentive is determined by the pool entered by the account and the specified vToken via `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\",\"params\":{\"account\":\"The account whose pool is used to determine the market's risk parameters\",\"vToken\":\"The address of the vToken market\"},\"returns\":{\"_0\":\"The liquidation Incentive for the vToken, scaled by 1e18\"}},\"getEffectiveLtvFactor(address,address,uint8)\":{\"details\":\"The value is determined by the pool entered by the account and the specified vToken via `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used. This value is used for account liquidity calculations and liquidation checks.\",\"params\":{\"account\":\"The account whose pool is used to determine the market's risk parameters.\",\"vToken\":\"The address of the vToken market.\",\"weightingStrategy\":\"The weighting strategy to use: - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\"},\"returns\":{\"_0\":\"factor The effective loan-to-value factor, scaled by 1e18.\"}},\"getLiquidationIncentive(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the liquidation Incentive for\"},\"returns\":{\"_0\":\"liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\"}},\"getLiquidationThreshold(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the liquidation threshold for\"},\"returns\":{\"_0\":\"The liquidation threshold for the vToken, scaled by 1e18\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getPoolVTokens(uint96)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the given pool ID do not exist.InvalidOperationForCorePool Reverts if called on the Core Pool.\",\"params\":{\"poolId\":\"The ID of the pool whose vTokens are being queried.\"},\"returns\":{\"_0\":\"An array of vToken addresses associated with the pool.\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"hasValidPoolBorrows(address,uint96)\":{\"params\":{\"account\":\"The address of the user attempting to switch pools.\",\"targetPoolId\":\"The pool ID the user wants to switch into.\"},\"returns\":{\"_0\":\"bool True if the switch is allowed, otherwise False.\"}},\"isMarketListed(address)\":{\"params\":{\"vToken\":\"The vToken Address of the market to check\"},\"returns\":{\"_0\":\"listed True if the (Core Pool, vToken) market is listed, otherwise false\"}},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"borrower\":\"Address of borrower whose collateral is being seized\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"liquidateVAICalculateSeizeTokens(address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"markets(address)\":{\"details\":\"Fetches the Market struct associated with the core pool and returns all relevant parameters.\",\"params\":{\"vToken\":\"The address of the vToken whose market configuration is to be fetched.\"},\"returns\":{\"collateralFactorMantissa\":\"The maximum borrowable percentage of collateral, in mantissa.\",\"isBorrowAllowed\":\"Whether borrowing is allowed in this market.\",\"isListed\":\"Whether the market is listed and enabled.\",\"isVenus\":\"Whether this market is eligible for VENUS rewards.\",\"liquidationIncentiveMantissa\":\"The max liquidation incentive allowed for this market, in mantissa.\",\"liquidationThresholdMantissa\":\"The threshold at which liquidation is triggered, in mantissa.\",\"marketPoolId\":\"The pool ID this market belongs to.\"}},\"poolMarkets(uint96,address)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the given pool ID do not exist.\",\"details\":\"Fetches the Market struct associated with the poolId and returns all relevant parameters.\",\"params\":{\"poolId\":\"The ID of the pool whose market configuration is being queried.\",\"vToken\":\"The address of the vToken whose market configuration is to be fetched.\"},\"returns\":{\"collateralFactorMantissa\":\"The maximum borrowable percentage of collateral, in mantissa.\",\"isBorrowAllowed\":\"Whether borrowing is allowed in this market.\",\"isListed\":\"Whether the market is listed and enabled.\",\"isVenus\":\"Whether this market is eligible for XVS rewards.\",\"liquidationIncentiveMantissa\":\"The liquidation incentive allowed for this market, in mantissa.\",\"liquidationThresholdMantissa\":\"The threshold at which liquidation is triggered, in mantissa.\",\"marketPoolId\":\"The pool ID this market belongs to.\"}},\"removePoolMarket(uint96,address)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts if called on the Core Pool.PoolMarketNotFound Reverts if the market is not listed in the pool.\",\"custom:event\":\"PoolMarketRemoved Emitted after a market is successfully removed from a pool.\",\"params\":{\"poolId\":\"The ID of the pool from which the market should be removed.\",\"vToken\":\"The address of the market token to remove.\"}},\"supportMarket(address)\":{\"params\":{\"vToken\":\"The address of the market (token) to list\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"unlistMarket(address)\":{\"details\":\"Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\",\"params\":{\"market\":\"The address of the market (vToken) to unlist\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (See enum Error for details)\"}},\"updateDelegate(address,bool)\":{\"params\":{\"approved\":\"Whether to grant (true) or revoke (false) the borrowing or redeeming rights\",\"delegate\":\"The address to update the rights for\"}}},\"title\":\"MarketFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DelegateUpdated(address,address,bool)\":{\"notice\":\"Emitted when the borrowing or redeeming delegate rights are updated for an account\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"MarketExited(address,address)\":{\"notice\":\"Emitted when an account exits a market\"},\"MarketListed(address)\":{\"notice\":\"Emitted when an admin supports a market\"},\"MarketUnlisted(address)\":{\"notice\":\"Emitted when an admin unlists a market\"},\"PoolCreated(uint96,string)\":{\"notice\":\"Emitted when a new pool is created\"},\"PoolMarketInitialized(uint96,address)\":{\"notice\":\"Emitted when a market is initialized in a pool\"},\"PoolMarketRemoved(uint96,address)\":{\"notice\":\"Emitted when a vToken market is removed from a pool\"},\"PoolSelected(address,uint96,uint96)\":{\"notice\":\"Emitted when a user enters or exits a pool (poolId = 0 means exit)\"}},\"kind\":\"user\",\"methods\":{\"_supportMarket(address)\":{\"notice\":\"Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"addPoolMarkets(uint96[],address[])\":{\"notice\":\"Batch initializes market entries with basic config.\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account has entered the specified vToken market in the Core Pool\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"createPool(string)\":{\"notice\":\"Creates a new pool with the given label.\"},\"enterMarketBehalf(address,address)\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"enterPool(uint96)\":{\"notice\":\"Allows a user to switch to a new pool (e.g., e-mode ).\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the vToken markets an account has entered in the Core Pool\"},\"getCollateralFactor(address)\":{\"notice\":\"Get the core pool collateral factor for a vToken\"},\"getEffectiveLiquidationIncentive(address,address)\":{\"notice\":\"Get the Effective Liquidation Incentive for a given account and market\"},\"getEffectiveLtvFactor(address,address,uint8)\":{\"notice\":\"Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\"},\"getLiquidationIncentive(address)\":{\"notice\":\"Get the core pool liquidation Incentive for a vToken\"},\"getLiquidationThreshold(address)\":{\"notice\":\"Get the core pool liquidation threshold for a vToken\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getPoolVTokens(uint96)\":{\"notice\":\"Returns the full list of vTokens for a given pool ID.\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"hasValidPoolBorrows(address,uint96)\":{\"notice\":\"Returns true if the user can switch to the given target pool, i.e., all markets they have borrowed from are also borrowable in the target pool.\"},\"isComptroller()\":{\"notice\":\"Indicator that this is a Comptroller contract (for inspection)\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"isMarketListed(address)\":{\"notice\":\"Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidateVAICalculateSeizeTokens(address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"markets(address)\":{\"notice\":\"Returns the market configuration for a vToken in the core pool (poolId = 0).\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"poolMarkets(uint96,address)\":{\"notice\":\"Returns the market configuration for a vToken from _poolMarkets.\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"removePoolMarket(uint96,address)\":{\"notice\":\"Removes a market (vToken) from the specified pool.\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"supportMarket(address)\":{\"notice\":\"Alias to _supportMarket to support the Isolated Lending Comptroller Interface\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"unlistMarket(address)\":{\"notice\":\"Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\"},\"updateDelegate(address,bool)\":{\"notice\":\"Grants or revokes the borrowing or redeeming delegate rights to / from an account If allowed, the delegate will be able to borrow funds on behalf of the sender Upon a delegated borrow, the delegate will receive the funds, and the borrower will see the debt on their account Upon a delegated redeem, the delegate will receive the redeemed amount and the approver will see a deduction in his vToken balance\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains functions regarding markets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/MarketFacet.sol\":\"MarketFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/MarketFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IMarketFacet } from \\\"../interfaces/IMarketFacet.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title MarketFacet\\n * @author Venus\\n * @dev This facet contains all the methods related to the market's management in the pool\\n * @notice This facet contract contains functions regarding markets\\n */\\ncontract MarketFacet is IMarketFacet, FacetBase {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(VToken indexed vToken);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account\\n event DelegateUpdated(address indexed approver, address indexed delegate, bool approved);\\n\\n /// @notice Emitted when an admin unlists a market\\n event MarketUnlisted(address indexed vToken);\\n\\n /// @notice Emitted when a market is initialized in a pool\\n event PoolMarketInitialized(uint96 indexed poolId, address indexed market);\\n\\n /// @notice Emitted when a user enters or exits a pool (poolId = 0 means exit)\\n event PoolSelected(address indexed account, uint96 previousPoolId, uint96 indexed newPoolId);\\n\\n /// @notice Emitted when a vToken market is removed from a pool\\n event PoolMarketRemoved(uint96 indexed poolId, address indexed vToken);\\n\\n /// @notice Emitted when a new pool is created\\n event PoolCreated(uint96 indexed poolId, string label);\\n\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() public pure returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Returns the vToken markets an account has entered in the Core Pool\\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\\n * @param account The address of the account to query\\n * @return assets A dynamic array of vToken markets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n uint256 len;\\n VToken[] memory _accountAssets = accountAssets[account];\\n uint256 _accountAssetsLength = _accountAssets.length;\\n\\n VToken[] memory assetsIn = new VToken[](_accountAssetsLength);\\n\\n for (uint256 i; i < _accountAssetsLength; ++i) {\\n Market storage market = getCorePoolMarket(address(_accountAssets[i]));\\n if (market.isListed) {\\n assetsIn[len] = _accountAssets[i];\\n ++len;\\n }\\n }\\n\\n assembly {\\n mstore(assetsIn, len)\\n }\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market\\n * @return The list of market addresses\\n */\\n function getAllMarkets() external view returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\\n address(this),\\n vTokenBorrowed,\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param borrower Address of borrower whose collateral is being seized\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n vTokenBorrowed,\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\\n address(this),\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns whether the given account has entered the specified vToken market in the Core Pool\\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the asset, otherwise false\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return getCorePoolMarket(address(vToken)).accountMembership[account];\\n }\\n\\n /**\\n * @notice Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken Address of the market to check\\n * @return listed True if the (Core Pool, vToken) market is listed, otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return getCorePoolMarket(address(vToken)).isListed;\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @dev Only callable by the account itself or an approved delegate\\n * @param onBehalf The address of the account entering the market\\n * @param vToken The address of the vToken market to enable for the account\\n * @return uint256 indicating the result (0 = success, non-zero = failure)\\n * @custom:error NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\\n */\\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256) {\\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\\n revert NotAnApprovedDelegate();\\n }\\n return uint256(addToMarketInternal(VToken(vToken), onBehalf));\\n }\\n\\n /**\\n * @notice Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\\n * @dev Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\\n * @param market The address of the market (vToken) to unlist\\n * @return uint256 0=success, otherwise a failure (See enum Error for details)\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n ensureAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = getCorePoolMarket(market);\\n\\n if (!_market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.UNLIST_MARKET_NOT_LISTED);\\n }\\n\\n require(actionPaused(market, Action.BORROW), \\\"borrow action is not paused\\\");\\n require(actionPaused(market, Action.MINT), \\\"mint action is not paused\\\");\\n require(actionPaused(market, Action.REDEEM), \\\"redeem action is not paused\\\");\\n require(actionPaused(market, Action.REPAY), \\\"repay action is not paused\\\");\\n require(actionPaused(market, Action.ENTER_MARKET), \\\"enter market action is not paused\\\");\\n require(actionPaused(market, Action.LIQUIDATE), \\\"liquidate action is not paused\\\");\\n require(actionPaused(market, Action.SEIZE), \\\"seize action is not paused\\\");\\n require(actionPaused(market, Action.TRANSFER), \\\"transfer action is not paused\\\");\\n require(actionPaused(market, Action.EXIT_MARKET), \\\"exit market action is not paused\\\");\\n\\n require(borrowCaps[market] == 0, \\\"borrow cap is not 0\\\");\\n require(supplyCaps[market] == 0, \\\"supply cap is not 0\\\");\\n\\n require(_market.collateralFactorMantissa == 0, \\\"collateral factor is not 0\\\");\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow\\n * @param vTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address vTokenAddress) external returns (uint256) {\\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = getCorePoolMarket(address(vToken));\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n uint256 i;\\n for (; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n userAssetList[i] = userAssetList[len - 1];\\n userAssetList.pop();\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(i < len);\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Alias to _supportMarket to support the Isolated Lending Comptroller Interface\\n * @param vToken The address of the market (token) to list\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function supportMarket(VToken vToken) external returns (uint256) {\\n return __supportMarket(vToken);\\n }\\n\\n /**\\n * @notice Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\\n * @dev Allows a privileged role to add and list markets to the Comptroller\\n * @param vToken The address of the vToken market to list in the Core Pool\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(VToken vToken) external returns (uint256) {\\n return __supportMarket(vToken);\\n }\\n\\n /**\\n * @notice Grants or revokes the borrowing or redeeming delegate rights to / from an account\\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\\n * will see the debt on their account\\n * Upon a delegated redeem, the delegate will receive the redeemed amount and the approver\\n * will see a deduction in his vToken balance\\n * @param delegate The address to update the rights for\\n * @param approved Whether to grant (true) or revoke (false) the borrowing or redeeming rights\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n require(approvedDelegates[msg.sender][delegate] != approved, \\\"Delegation status unchanged\\\");\\n\\n _updateDelegate(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Allows a user to switch to a new pool (e.g., e-mode ).\\n * @param poolId The ID of the pool the user wants to enter.\\n * @custom:error PoolDoesNotExist The specified pool ID does not exist.\\n * @custom:error AlreadyInSelectedPool The user is already in the target pool.\\n * @custom:error IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.\\n * @custom:error LiquidityCheckFailed The user's liquidity is insufficient after switching pools.\\n * @custom:error InactivePool The user is trying to enter inactive pool.\\n * @custom:event PoolSelected Emitted after a successful pool switch.\\n */\\n function enterPool(uint96 poolId) external {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n if (poolId == userPoolId[msg.sender]) {\\n revert AlreadyInSelectedPool();\\n }\\n\\n if (poolId != corePoolId && !pools[poolId].isActive) {\\n revert InactivePool(poolId);\\n }\\n\\n if (!hasValidPoolBorrows(msg.sender, poolId)) {\\n revert IncompatibleBorrowedAssets();\\n }\\n\\n emit PoolSelected(msg.sender, userPoolId[msg.sender], poolId);\\n\\n userPoolId[msg.sender] = poolId;\\n\\n (uint256 error, , uint256 shortfall) = _getAccountLiquidity(msg.sender, WeightFunction.USE_COLLATERAL_FACTOR);\\n\\n if (error != 0 || shortfall > 0) {\\n revert LiquidityCheckFailed(error, shortfall);\\n }\\n }\\n\\n /**\\n * @notice Creates a new pool with the given label.\\n * @param label name for the pool (must be non-empty).\\n * @return poolId The incremental unique identifier of the newly created pool.\\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string.\\n * @custom:event PoolCreated Emitted after successfully creating a new pool.\\n */\\n function createPool(string memory label) external returns (uint96) {\\n ensureAllowed(\\\"createPool(string)\\\");\\n\\n if (bytes(label).length == 0) {\\n revert EmptyPoolLabel();\\n }\\n\\n uint96 poolId = ++lastPoolId;\\n PoolData storage newPool = pools[poolId];\\n newPool.label = label;\\n newPool.isActive = true;\\n\\n emit PoolCreated(poolId, label);\\n return poolId;\\n }\\n\\n /**\\n * @notice Batch initializes market entries with basic config.\\n * @param poolIds Array of pool IDs.\\n * @param vTokens Array of market (vToken) addresses.\\n * @custom:error ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:error MarketNotListedInCorePool Reverts if the market is not listed in the core pool.\\n * @custom:error MarketAlreadyListed Reverts if the given market is already listed in the specified pool.\\n * @custom:error InactivePool Reverts if attempted to add markets to an inactive pool.\\n * @custom:event PoolMarketInitialized Emitted after successfully initializing a market in a pool.\\n */\\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external {\\n ensureAllowed(\\\"addPoolMarkets(uint96[],address[])\\\");\\n\\n uint256 len = poolIds.length;\\n if (len == 0 || len != vTokens.length) {\\n revert ArrayLengthMismatch();\\n }\\n\\n for (uint256 i; i < len; i++) {\\n _addPoolMarket(poolIds[i], vTokens[i]);\\n }\\n }\\n\\n /**\\n * @notice Removes a market (vToken) from the specified pool.\\n * @param poolId The ID of the pool from which the market should be removed.\\n * @param vToken The address of the market token to remove.\\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\\n * @custom:error PoolMarketNotFound Reverts if the market is not listed in the pool.\\n * @custom:event PoolMarketRemoved Emitted after a market is successfully removed from a pool.\\n */\\n function removePoolMarket(uint96 poolId, address vToken) external {\\n ensureAllowed(\\\"removePoolMarket(uint96,address)\\\");\\n\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\\n if (!_poolMarkets[index].isListed) {\\n revert PoolMarketNotFound(poolId, vToken);\\n }\\n\\n address[] storage assets = pools[poolId].vTokens;\\n\\n uint256 length = assets.length;\\n for (uint256 i; i < length; i++) {\\n if (assets[i] == vToken) {\\n assets[i] = assets[length - 1];\\n assets.pop();\\n break;\\n }\\n }\\n\\n delete _poolMarkets[index];\\n\\n emit PoolMarketRemoved(poolId, vToken);\\n }\\n\\n /**\\n * @notice Get the core pool collateral factor for a vToken\\n * @param vToken The address of the vToken to get the collateral factor for\\n * @return The collateral factor for the vToken, scaled by 1e18\\n */\\n function getCollateralFactor(address vToken) external view returns (uint256) {\\n (uint256 cf, , ) = getLiquidationParams(corePoolId, vToken);\\n return cf;\\n }\\n\\n /**\\n * @notice Get the core pool liquidation threshold for a vToken\\n * @param vToken The address of the vToken to get the liquidation threshold for\\n * @return The liquidation threshold for the vToken, scaled by 1e18\\n */\\n function getLiquidationThreshold(address vToken) external view returns (uint256) {\\n (, uint256 lt, ) = getLiquidationParams(corePoolId, vToken);\\n return lt;\\n }\\n\\n /**\\n * @notice Get the core pool liquidation Incentive for a vToken\\n * @param vToken The address of the vToken to get the liquidation Incentive for\\n * @return liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\\n */\\n function getLiquidationIncentive(address vToken) external view returns (uint256) {\\n (, , uint256 li) = getLiquidationParams(corePoolId, vToken);\\n return li;\\n }\\n\\n /**\\n * @notice Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\\n * @dev The value is determined by the pool entered by the account and the specified vToken via\\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used.\\n * This value is used for account liquidity calculations and liquidation checks.\\n * @param account The account whose pool is used to determine the market's risk parameters.\\n * @param vToken The address of the vToken market.\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return factor The effective loan-to-value factor, scaled by 1e18.\\n */\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256) {\\n (uint256 cf, uint256 lt, ) = getLiquidationParams(userPoolId[account], vToken);\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) return cf;\\n else if (weightingStrategy == WeightFunction.USE_LIQUIDATION_THRESHOLD) return lt;\\n else revert InvalidWeightingStrategy(weightingStrategy);\\n }\\n\\n /**\\n * @notice Get the Effective Liquidation Incentive for a given account and market\\n * @dev The incentive is determined by the pool entered by the account and the specified vToken via\\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\\n * @param account The account whose pool is used to determine the market's risk parameters\\n * @param vToken The address of the vToken market\\n * @return The liquidation Incentive for the vToken, scaled by 1e18\\n */\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256) {\\n (, , uint256 li) = getLiquidationParams(userPoolId[account], vToken);\\n return li;\\n }\\n\\n /**\\n * @notice Returns the full list of vTokens for a given pool ID.\\n * @param poolId The ID of the pool whose vTokens are being queried.\\n * @return An array of vToken addresses associated with the pool.\\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\\n */\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory) {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n return pools[poolId].vTokens;\\n }\\n\\n /**\\n * @notice Returns the market configuration for a vToken in the core pool (poolId = 0).\\n * @dev Fetches the Market struct associated with the core pool and returns all relevant parameters.\\n * @param vToken The address of the vToken whose market configuration is to be fetched.\\n * @return isListed Whether the market is listed and enabled.\\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\\n * @return isVenus Whether this market is eligible for VENUS rewards.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The max liquidation incentive allowed for this market, in mantissa.\\n * @return marketPoolId The pool ID this market belongs to.\\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\\n */\\n function markets(\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n )\\n {\\n return poolMarkets(corePoolId, vToken);\\n }\\n\\n /**\\n * @notice Returns the market configuration for a vToken from _poolMarkets.\\n * @dev Fetches the Market struct associated with the poolId and returns all relevant parameters.\\n * @param poolId The ID of the pool whose market configuration is being queried.\\n * @param vToken The address of the vToken whose market configuration is to be fetched.\\n * @return isListed Whether the market is listed and enabled.\\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\\n * @return isVenus Whether this market is eligible for XVS rewards.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\\n * @return marketPoolId The pool ID this market belongs to.\\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\\n */\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n public\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n )\\n {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n PoolMarketId key = getPoolMarketIndex(poolId, vToken);\\n Market storage m = _poolMarkets[key];\\n\\n return (\\n m.isListed,\\n m.collateralFactorMantissa,\\n m.isVenus,\\n m.liquidationThresholdMantissa,\\n m.liquidationIncentiveMantissa,\\n m.poolId,\\n m.isBorrowAllowed\\n );\\n }\\n\\n /**\\n * @notice Returns true if the user can switch to the given target pool, i.e.,\\n * all markets they have borrowed from are also borrowable in the target pool.\\n * @param account The address of the user attempting to switch pools.\\n * @param targetPoolId The pool ID the user wants to switch into.\\n * @return bool True if the switch is allowed, otherwise False.\\n */\\n function hasValidPoolBorrows(address account, uint96 targetPoolId) public view returns (bool) {\\n VToken[] memory assets = accountAssets[account];\\n if (targetPoolId != corePoolId && mintedVAIs[account] > 0) {\\n return false;\\n }\\n\\n for (uint256 i; i < assets.length; i++) {\\n VToken vToken = assets[i];\\n PoolMarketId index = getPoolMarketIndex(targetPoolId, address(vToken));\\n\\n if (!_poolMarkets[index].isBorrowAllowed) {\\n if (vToken.borrowBalanceStored(account) > 0) {\\n return false;\\n }\\n }\\n }\\n return true;\\n }\\n\\n function _updateDelegate(address approver, address delegate, bool approved) internal {\\n approvedDelegates[approver][delegate] = approved;\\n emit DelegateUpdated(approver, delegate, approved);\\n }\\n\\n function _addMarketInternal(VToken vToken) internal {\\n uint256 allMarketsLength = allMarkets.length;\\n for (uint256 i; i < allMarketsLength; ++i) {\\n require(allMarkets[i] != vToken, \\\"already added\\\");\\n }\\n allMarkets.push(vToken);\\n }\\n\\n function _initializeMarket(address vToken) internal {\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = venusInitialIndex;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = venusInitialIndex;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n function __supportMarket(VToken vToken) internal returns (uint256) {\\n ensureAllowed(\\\"_supportMarket(address)\\\");\\n\\n if (getCorePoolMarket(address(vToken)).isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n vToken.isVToken(); // Sanity check to make sure its really a VToken\\n\\n // Note that isVenus is not in active use anymore\\n Market storage newMarket = getCorePoolMarket(address(vToken));\\n newMarket.isListed = true;\\n newMarket.isVenus = false;\\n newMarket.collateralFactorMantissa = 0;\\n\\n _addMarketInternal(vToken);\\n _initializeMarket(address(vToken));\\n\\n emit MarketListed(vToken);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n function _addPoolMarket(uint96 poolId, address vToken) internal {\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (!pools[poolId].isActive) revert InactivePool(poolId);\\n\\n // Core Pool Index\\n PoolMarketId index = getPoolMarketIndex(corePoolId, vToken);\\n if (!_poolMarkets[index].isListed) revert MarketNotListedInCorePool();\\n\\n // Pool Index\\n index = getPoolMarketIndex(poolId, vToken);\\n if (_poolMarkets[index].isListed) revert MarketAlreadyListed(poolId, vToken);\\n\\n Market storage m = _poolMarkets[index];\\n m.poolId = poolId;\\n m.isListed = true;\\n\\n pools[poolId].vTokens.push(vToken);\\n\\n emit PoolMarketInitialized(poolId, vToken);\\n }\\n\\n /**\\n * @notice Returns only the core risk parameters (CF, LI, LT) for a vToken in a specific pool.\\n * @dev If the pool is inactive, or if the vToken is not configured in the given pool and\\n * `allowCorePoolFallback` is enabled, falls back to the core pool (poolId = 0) values.\\n * @return collateralFactorMantissa The max borrowable percentage of collateral, in mantissa.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\\n */\\n function getLiquidationParams(\\n uint96 poolId,\\n address vToken\\n )\\n internal\\n view\\n returns (\\n uint256 collateralFactorMantissa,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa\\n )\\n {\\n PoolData storage pool = pools[poolId];\\n Market storage market;\\n\\n if (poolId == corePoolId || !pool.isActive) {\\n market = getCorePoolMarket(vToken);\\n } else {\\n PoolMarketId poolKey = getPoolMarketIndex(poolId, vToken);\\n Market storage poolMarket = _poolMarkets[poolKey];\\n market = (!poolMarket.isListed && pool.allowCorePoolFallback) ? getCorePoolMarket(vToken) : poolMarket;\\n }\\n\\n return (\\n market.collateralFactorMantissa,\\n market.liquidationThresholdMantissa,\\n market.liquidationIncentiveMantissa\\n );\\n }\\n}\\n\",\"keccak256\":\"0x168e841b9538dd463ebe73235cbb9a15be601b476c1efbfae81d38dcdb989421\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IMarketFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./IFacetBase.sol\\\";\\n\\ninterface IMarketFacet {\\n function isComptroller() external pure returns (bool);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function checkMembership(address account, VToken vToken) external view returns (bool);\\n\\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256);\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n function _supportMarket(VToken vToken) external returns (uint256);\\n\\n function supportMarket(VToken vToken) external returns (uint256);\\n\\n function isMarketListed(VToken vToken) external view returns (bool);\\n\\n function getAssetsIn(address account) external view returns (VToken[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function updateDelegate(address delegate, bool allowBorrows) external;\\n\\n function unlistMarket(address market) external returns (uint256);\\n\\n function createPool(string memory label) external returns (uint96);\\n\\n function enterPool(uint96 poolId) external;\\n\\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external;\\n\\n function removePoolMarket(uint96 poolId, address vToken) external;\\n\\n function markets(\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function hasValidPoolBorrows(address user, uint96 targetPoolId) external view returns (bool);\\n\\n function getCollateralFactor(address vToken) external view returns (uint256);\\n\\n function getLiquidationThreshold(address vToken) external view returns (uint256);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x11118e9ea5b6c8df34d55ae85f4310ef9f6a7590b3a2202fbc7a2bb0b8572699\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506138168061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061044d575f3560e01c806396c9906411610242578063cab4f84c11610140578063e0f6123d116100bf578063f02fdf9711610084578063f02fdf9714610b48578063f445d70314610b5b578063f851a44014610b88578063f968273214610b9a578063fa6331d814610bad575f80fd5b8063e0f6123d14610ac0578063e37d4b7914610ae2578063e85a296014610b19578063e875544614610b2c578063ede4edd014610b35575f80fd5b8063d585c3c611610105578063d585c3c614610a61578063d686e9ee14610a74578063dce1544914610a87578063dcfbc0c714610a9a578063ddbf54fd14610aad575f80fd5b8063cab4f84c1461088c578063d0d1303614610a21578063d137f36e14610a34578063d3270f9914610a47578063d463654c14610a5a575f80fd5b8063b8324c7c116101cc578063c299823811610191578063c29982381461099a578063c488847b146109ba578063c5b4db55146109cd578063c5f956af146109fb578063c7ee005e14610a0e575f80fd5b8063b8324c7c146108f3578063bb82aa5e1461094e578063bbb8864a14610961578063bec04f7214610980578063bf32442d14610989575f80fd5b8063a78dc77511610212578063a78dc7751461089f578063abfceffc146108b2578063afd3783b146108c5578063b0772d0b146108d8578063b2eafc39146108e0575f80fd5b806396c99064146108445780639bb27d6214610866578063a657e57914610879578063a76b3fda1461088c575f80fd5b80634a5844321161034f5780637d172bd5116102d95780638c1ac18a1161029e5780638c1ac18a146107e05780638e8f294b146108025780639254f5e514610815578063929fe9a11461082857806394b2294b1461083b575f80fd5b80637d172bd5146107795780637dc0d1d01461078c5780637fb8e8cd1461079f57806389c13be0146107ac5780638a7dc165146107c1575f80fd5b806363e0d6341161031f57806363e0d634146106eb578063719f701b1461070b578063737690991461071457806376551383146107545780637b86e42c14610766575f80fd5b80634a584432146106875780634d99c776146106a657806352d84d1e146106b95780635dd3fc9d146106cc575f80fd5b806321af4569116103db5780633093c11e116103a05780633093c11e146105d05780633d98a1e51461062a5780634088c73e1461063d57806341a18d2c1461064a578063425fad5814610674575f80fd5b806321af45691461054d578063236175851461057857806324a3d6221461058b578063267822471461059e5780632bc7e29e146105b1575f80fd5b806308e0225c1161042157806308e0225c146104b25780630db4b4e5146104dc5780630ef332ca146104e557806310b983381461050d57806319ef3e8b1461053a575f80fd5b80627e3dd21461045157806302c3bcbb1461046957806304ef9d58146104965780630686dab61461049f575b5f80fd5b60015b60405190151581526020015b60405180910390f35b610488610477366004612fa8565b60276020525f908152604090205481565b604051908152602001610460565b61048860225481565b6104886104ad366004612fa8565b610bb6565b6104886104c0366004612fc3565b601360209081525f928352604080842090915290825290205481565b610488601d5481565b6104f86104f3366004612ffa565b61107c565b60408051928352602083019190915201610460565b61045461051b366004612fc3565b602c60209081525f928352604080842090915290825290205460ff1681565b610488610548366004613048565b611119565b601e54610560906001600160a01b031681565b6040516001600160a01b039091168152602001610460565b610488610586366004612fa8565b6111ab565b600a54610560906001600160a01b031681565b600154610560906001600160a01b031681565b6104886105bf366004612fa8565b60166020525f908152604090205481565b6105e36105de3660046130ae565b6111c1565b604080519715158852602088019690965293151594860194909452606085019190915260808401526001600160601b0390911660a0830152151560c082015260e001610460565b610454610638366004612fa8565b611286565b6018546104549060ff1681565b610488610658366004612fc3565b601260209081525f928352604080842090915290825290205481565b6018546104549062010000900460ff1681565b610488610695366004612fa8565b601f6020525f908152604090205481565b6104886106b43660046130ae565b61129a565b6105606106c73660046130c8565b6112bb565b6104886106da366004612fa8565b602b6020525f908152604090205481565b6106fe6106f93660046130df565b6112e3565b60405161046091906130f8565b610488601c5481565b61073c610722366004612fa8565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610460565b60185461045490610100900460ff1681565b610488610774366004612fa8565b6113bc565b601b54610560906001600160a01b031681565b600454610560906001600160a01b031681565b6039546104549060ff1681565b6107bf6107ba366004613185565b6113d1565b005b6104886107cf366004612fa8565b60146020525f908152604090205481565b6104546107ee366004612fa8565b602d6020525f908152604090205460ff1681565b6105e3610810366004612fa8565b61148e565b601554610560906001600160a01b031681565b610454610836366004612fc3565b6114b6565b61048860075481565b6108576108523660046130df565b6114e5565b6040516104609392919061321a565b602554610560906001600160a01b031681565b60375461073c906001600160601b031681565b61048861089a366004612fa8565b611592565b6104f86108ad366004613243565b61159c565b6106fe6108c0366004612fa8565b611629565b6104886108d3366004612fc3565b611786565b6106fe6117bd565b602054610560906001600160a01b031681565b61092a610901366004612fa8565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610460565b600254610560906001600160a01b031681565b61048861096f366004612fa8565b602a6020525f908152604090205481565b61048860175481565b6033546001600160a01b0316610560565b6109ad6109a836600461326d565b61181d565b60405161046091906132ac565b6104f86109c83660046132e3565b6118d6565b6109e36ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b039091168152602001610460565b602154610560906001600160a01b031681565b603154610560906001600160a01b031681565b61073c610a2f366004613335565b61196a565b6107bf610a423660046130ae565b611a70565b602654610560906001600160a01b031681565b61073c5f81565b610488610a6f366004612fc3565b611cca565b610488610a82366004612fa8565b611d40565b610560610a95366004613243565b611d55565b600354610560906001600160a01b031681565b6107bf610abb3660046133ed565b611d89565b610454610ace366004612fa8565b60386020525f908152604090205460ff1681565b61092a610af0366004612fa8565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b610454610b27366004613419565b611e1b565b61048860055481565b610488610b43366004612fa8565b611e5f565b610454610b56366004613448565b612108565b610454610b69366004612fc3565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610560906001600160a01b031681565b6107bf610ba83660046130df565b612297565b610488601a5481565b5f610bed60405180604001604052806015815260200174756e6c6973744d61726b657428616464726573732960581b81525061245b565b5f610bf78361250b565b805490915060ff16610c1657610c0f6009601861252d565b9392505050565b610c21836002611e1b565b610c725760405162461bcd60e51b815260206004820152601b60248201527f626f72726f7720616374696f6e206973206e6f7420706175736564000000000060448201526064015b60405180910390fd5b610c7c835f611e1b565b610cc85760405162461bcd60e51b815260206004820152601960248201527f6d696e7420616374696f6e206973206e6f7420706175736564000000000000006044820152606401610c69565b610cd3836001611e1b565b610d1f5760405162461bcd60e51b815260206004820152601b60248201527f72656465656d20616374696f6e206973206e6f742070617573656400000000006044820152606401610c69565b610d2a836003611e1b565b610d765760405162461bcd60e51b815260206004820152601a60248201527f726570617920616374696f6e206973206e6f74207061757365640000000000006044820152606401610c69565b610d81836007611e1b565b610dd75760405162461bcd60e51b815260206004820152602160248201527f656e746572206d61726b657420616374696f6e206973206e6f742070617573656044820152601960fa1b6064820152608401610c69565b610de2836005611e1b565b610e2e5760405162461bcd60e51b815260206004820152601e60248201527f6c697175696461746520616374696f6e206973206e6f742070617573656400006044820152606401610c69565b610e39836004611e1b565b610e855760405162461bcd60e51b815260206004820152601a60248201527f7365697a6520616374696f6e206973206e6f74207061757365640000000000006044820152606401610c69565b610e90836006611e1b565b610edc5760405162461bcd60e51b815260206004820152601d60248201527f7472616e7366657220616374696f6e206973206e6f74207061757365640000006044820152606401610c69565b610ee7836008611e1b565b610f335760405162461bcd60e51b815260206004820181905260248201527f65786974206d61726b657420616374696f6e206973206e6f74207061757365646044820152606401610c69565b6001600160a01b0383165f908152601f602052604090205415610f8e5760405162461bcd60e51b81526020600482015260136024820152720626f72726f7720636170206973206e6f74203606c1b6044820152606401610c69565b6001600160a01b0383165f9081526027602052604090205415610fe95760405162461bcd60e51b81526020600482015260136024820152720737570706c7920636170206973206e6f74203606c1b6044820152606401610c69565b60018101541561103b5760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206973206e6f7420300000000000006044820152606401610c69565b805460ff191681556040516001600160a01b038416907f302feb03efd5741df80efe7f97f5d93d74d46a542a3d312d0faae64fa1f3e0e9905f90a25f610c0f565b602654604051630a5d5a0560e41b81526001600160a01b03868116600483015230602483015285811660448301528481166064830152608482018490525f92839283928392169063a5d5a0509060a4016040805180830381865afa1580156110e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110a919061348f565b90999098509650505050505050565b6001600160a01b0383165f9081526035602052604081205481908190611148906001600160601b0316866125a4565b5090925090505f8460018111156111615761116161347b565b0361116e57509050610c0f565b60018460018111156111825761118261347b565b03611190579150610c0f9050565b83604051632f03799f60e11b8152600401610c6991906134d1565b5f806111b75f846125a4565b5090949350505050565b5f805f805f805f60375f9054906101000a90046001600160601b03166001600160601b0316896001600160601b0316111561121a57604051632db8671b60e11b81526001600160601b038a166004820152602401610c69565b5f6112258a8a61129a565b5f9081526009602052604090208054600182015460038301546004840154600585015460069095015460ff9485169d50929b50908316995097509195506001600160601b0382169450600160601b9091041691505092959891949750929550565b5f6112908261250b565b5460ff1692915050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d81815481106112ca575f80fd5b5f918252602090912001546001600160a01b0316905081565b6037546060906001600160601b03908116908316111561132157604051632db8671b60e11b81526001600160601b0383166004820152602401610c69565b6001600160601b03821661134857604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f90815260366020908152604091829020600101805483518184028101840190945280845290918301828280156113b057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611392575b50505050509050919050565b5f806113c85f846125a4565b50949350505050565b6113f26040518060600160405280602281526020016137bf6022913961245b565b828015806114005750808214155b1561141e5760405163512509d360e11b815260040160405180910390fd5b5f5b818110156114865761147e86868381811061143d5761143d6134df565b905060200201602081019061145291906130df565b858584818110611464576114646134df565b90506020020160208101906114799190612fa8565b612656565b600101611420565b505050505050565b5f805f805f805f61149f5f896111c1565b959e949d50929b5090995097509550909350915050565b5f6114c08261250b565b6001600160a01b03939093165f90815260029093016020525050604090205460ff1690565b60366020525f90815260409020805481906114ff906134f3565b80601f016020809104026020016040519081016040528092919081815260200182805461152b906134f3565b80156115765780601f1061154d57610100808354040283529160200191611576565b820191905f5260205f20905b81548152906001019060200180831161155957829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6112b582612839565b6026546040516304f65f8b60e21b81523060048201526001600160a01b038481166024830152604482018490525f9283928392839216906313d97e2c906064016040805180830381865afa1580156115f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061161a919061348f565b909450925050505b9250929050565b6001600160a01b0381165f908152600860209081526040808320805482518185028101850190935280835260609493849392919083018282801561169457602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611676575b505050505090505f815190505f8167ffffffffffffffff8111156116ba576116ba613321565b6040519080825280602002602001820160405280156116e3578160200160208202803683370190505b5090505f5b82811015611779575f611713858381518110611706576117066134df565b602002602001015161250b565b805490915060ff161561177057848281518110611732576117326134df565b602002602001015183878151811061174c5761174c6134df565b6001600160a01b039092166020928302919091019091015261176d8661353f565b95505b506001016116e8565b5092835250909392505050565b6001600160a01b0382165f9081526035602052604081205481906117b3906001600160601b0316846125a4565b9695505050505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561181357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116117f5575b5050505050905090565b6060815f8167ffffffffffffffff81111561183a5761183a613321565b604051908082528060200260200182016040528015611863578160200160208202803683370190505b5090505f5b828110156113c8576118a0868683818110611885576118856134df565b905060200201602081019061189a9190612fa8565b3361296d565b60148111156118b1576118b161347b565b8282815181106118c3576118c36134df565b6020908102919091010152600101611868565b602654604051630779996560e11b81523060048201526001600160a01b0385811660248301528481166044830152606482018490525f928392839283921690630ef332ca906084016040805180830381865afa158015611938573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061195c919061348f565b909890975095505050505050565b5f61199e60405180604001604052806012815260200171637265617465506f6f6c28737472696e672960701b81525061245b565b81515f036119bf5760405163522e397360e11b815260040160405180910390fd5b603780545f919082906119da906001600160601b0316613557565b82546001600160601b038083166101009490940a848102910219909116179092555f90815260366020526040902090915080611a1685826135c7565b5060028101805460ff191660011790556040516001600160601b038316907fc419386a8582a5374f4db03fdbb9fd99c73ef32d6ce9fc3a8c249e97bf31f9af90611a61908790613683565b60405180910390a25092915050565b611aae6040518060400160405280602081526020017f72656d6f7665506f6f6c4d61726b65742875696e7439362c616464726573732981525061245b565b6001600160601b038216611ad557604051630203217b60e61b815260040160405180910390fd5b5f611ae0838361129a565b5f8181526009602052604090205490915060ff16611b2b576040516338ddb96b60e11b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c69565b6001600160601b0383165f908152603660205260408120600101805490915b81811015611c3857846001600160a01b0316838281548110611b6e57611b6e6134df565b5f918252602090912001546001600160a01b031603611c305782611b93600184613695565b81548110611ba357611ba36134df565b905f5260205f20015f9054906101000a90046001600160a01b0316838281548110611bd057611bd06134df565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480611c0b57611c0b6136a8565b5f8281526020902081015f1990810180546001600160a01b0319169055019055611c38565b600101611b4a565b505f83815260096020526040808220805460ff199081168255600182018490556003820180549091169055600481018390556005810183905560060180546cffffffffffffffffffffffffff19169055516001600160a01b038616916001600160601b038816917fc8bef274db6d8c804aba68a69e64268bcfe7dd0aead2efcec0cac73a2df56e129190a35050505050565b5f336001600160a01b03841614801590611d0757506001600160a01b0383165f908152602c6020908152604080832033845290915290205460ff16155b15611d25576040516337248ad960e01b815260040160405180910390fd5b611d2f828461296d565b6014811115610c0f57610c0f61347b565b5f80611d4c5f846125a4565b95945050505050565b6008602052815f5260405f208181548110611d6e575f80fd5b5f918252602090912001546001600160a01b03169150829050565b611d9282612a40565b335f908152602c602090815260408083206001600160a01b038616845290915290205481151560ff909116151503611e0c5760405162461bcd60e51b815260206004820152601b60248201527f44656c65676174696f6e2073746174757320756e6368616e67656400000000006044820152606401610c69565b611e17338383612a8e565b5050565b6001600160a01b0382165f90815260296020526040812081836008811115611e4557611e4561347b565b815260208101919091526040015f205460ff169392505050565b5f611e6b826008612afa565b6040516361bfb47160e11b815233600482015282905f90819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa158015611eb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ed991906136bc565b50925092509250825f14611f2f5760405162461bcd60e51b815260206004820152601960248201527f6765744163636f756e74536e617073686f74206661696c6564000000000000006044820152606401610c69565b8015611f41576117b3600c600261252d565b5f611f4d873385612b44565b90508015611f6d57611f62600e600383612beb565b979650505050505050565b5f611f778661250b565b335f90815260028201602052604090205490915060ff16611f9f575f98975050505050505050565b335f9081526002820160209081526040808320805460ff1916905560089091528120805490915b818110156120b457886001600160a01b0316838281548110611fea57611fea6134df565b5f918252602090912001546001600160a01b0316036120ac578261200f600184613695565b8154811061201f5761201f6134df565b905f5260205f20015f9054906101000a90046001600160a01b031683828154811061204c5761204c6134df565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480612087576120876136a8565b5f8281526020902081015f1990810180546001600160a01b03191690550190556120b4565b600101611fc6565b8181106120c3576120c36136ef565b60405133906001600160a01b038b16907fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d905f90a35f9b9a5050505050505050505050565b6001600160a01b0382165f9081526008602090815260408083208054825181850281018501909352808352849383018282801561216c57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161214e575b50939450505050506001600160601b038316158015906121a257506001600160a01b0384165f9081526016602052604090205415155b156121b0575f9150506112b5565b5f5b815181101561228c575f8282815181106121ce576121ce6134df565b602002602001015190505f6121e3868361129a565b5f81815260096020526040902060060154909150600160601b900460ff16612282576040516395dd919360e01b81526001600160a01b0388811660048301525f91908416906395dd919390602401602060405180830381865afa15801561224c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122709190613703565b1115612282575f9450505050506112b5565b50506001016121b2565b506001949350505050565b6037546001600160601b0390811690821611156122d257604051632db8671b60e11b81526001600160601b0382166004820152602401610c69565b335f908152603560205260409020546001600160601b039081169082160361230d57604051631c9d4f3960e31b815260040160405180910390fd5b6001600160601b0381161580159061234057506001600160601b0381165f9081526036602052604090206002015460ff16155b1561236957604051632da4cc0560e01b81526001600160601b0382166004820152602401610c69565b6123733382612108565b6123905760405163592ec11d60e01b815260040160405180910390fd5b335f818152603560209081526040918290205491516001600160601b03928316815291841692917f9181876220501cdac3aa7278fd34e9bd150c30a27b6ed95458fe859761b071f7910160405180910390a3335f81815260356020526040812080546bffffffffffffffffffffffff19166001600160601b03851617905590819061241b9082612c6a565b9250509150815f14158061242e57505f81115b156124565760405163c978466160e01b81526004810183905260248101829052604401610c69565b505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab9061248d903390859060040161371a565b602060405180830381865afa1580156124a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124cc919061373d565b6125085760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610c69565b50565b5f60095f6125195f8561129a565b81526020019081526020015f209050919050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360148111156125615761256161347b565b83601a8111156125735761257361347b565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610c0f57610c0f61347b565b6001600160601b0382165f818152603660205260408120909182918291829015806125d45750600282015460ff16155b156125e9576125e28661250b565b9050612638565b5f6125f4888861129a565b5f81815260096020526040902080549192509060ff1615801561262057506002840154610100900460ff165b61262a5780612633565b6126338861250b565b925050505b80600101548160040154826005015494509450945050509250925092565b6001600160601b03821661267d57604051630203217b60e61b815260040160405180910390fd5b6037546001600160601b0390811690831611156126b857604051632db8671b60e11b81526001600160601b0383166004820152602401610c69565b6001600160601b0382165f9081526036602052604090206002015460ff166126fe57604051632da4cc0560e01b81526001600160601b0383166004820152602401610c69565b5f6127095f8361129a565b5f8181526009602052604090205490915060ff1661273a576040516386dccab760e01b815260040160405180910390fd5b612744838361129a565b5f8181526009602052604090205490915060ff16156127905760405163d9d72f2b60e01b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c69565b5f8181526009602090815260408083206006810180546bffffffffffffffffffffffff19166001600160601b038916908117909155815460ff19166001908117835581865260368552838620810180549182018155865293852090930180546001600160a01b0319166001600160a01b038816908117909155915190939192917f2159e9508e372ac69e1047a124c5478445206066e5d7df7e4214a1986cd78c8091a350505050565b5f6128786040518060400160405280601781526020017f5f737570706f72744d61726b657428616464726573732900000000000000000081525061245b565b6128818261250b565b5460ff1615612896576112b5600a601161252d565b816001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128f6919061373d565b505f6129018361250b565b8054600160ff19918216811783556003830180549092169091555f90820155905061292b83612ca2565b61293483612d78565b6040516001600160a01b038416907fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f905f90a25f610c0f565b5f612979836007612afa565b5f6129838461250b565b905061298e81612e3a565b6001600160a01b0383165f90815260028201602052604090205460ff16156129b9575f9150506112b5565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b6001600160a01b0381166125085760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610c69565b6001600160a01b038381165f818152602c6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fcb325b7784f78486e42849c7a50b8c5ee008d00cd90e108a58912c0fcb6288b4910160405180910390a3505050565b612b048282611e1b565b15611e175760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610c69565b5f612b56612b518561250b565b612e3a565b612b5f8461250b565b6001600160a01b0384165f908152600291909101602052604090205460ff16612b8957505f610c0f565b5f80612b988587865f80612e7f565b9193509091505f9050826014811115612bb357612bb361347b565b14612bd357816014811115612bca57612bca61347b565b92505050610c0f565b8015612be0576004612bca565b5f9695505050505050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846014811115612c1f57612c1f61347b565b84601a811115612c3157612c3161347b565b604080519283526020830191909152810184905260600160405180910390a1836014811115612c6257612c6261347b565b949350505050565b5f805f805f80612c7d885f805f8b612e7f565b925092509250826014811115612c9557612c9561347b565b9891975095509350505050565b600d545f5b81811015612d2557826001600160a01b0316600d8281548110612ccc57612ccc6134df565b5f918252602090912001546001600160a01b031603612d1d5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481859191959609a1b6044820152606401610c69565b600101612ca7565b5050600d80546001810182555f919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b5f612d81612f2c565b6001600160a01b0383165f908152601060209081526040808320601190925282208154939450909290916001600160e01b039091169003612ddc5781546001600160e01b0319166ec097ce7bc90715b34b9f10000000001782555b80546001600160e01b03165f03612e0d5780546001600160e01b0319166ec097ce7bc90715b34b9f10000000001781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b805460ff166125085760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610c69565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e90612ec59030908f908f908f908f908f90600401613758565b606060405180830381865afa158015612ee0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f049190613793565b925092509250826014811115612f1c57612f1c61347b565b9b919a5098509650505050505050565b5f612f604360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612f65565b905090565b5f816401000000008410612f8c5760405162461bcd60e51b8152600401610c699190613683565b509192915050565b6001600160a01b0381168114612508575f80fd5b5f60208284031215612fb8575f80fd5b8135610c0f81612f94565b5f8060408385031215612fd4575f80fd5b8235612fdf81612f94565b91506020830135612fef81612f94565b809150509250929050565b5f805f806080858703121561300d575f80fd5b843561301881612f94565b9350602085013561302881612f94565b9250604085013561303881612f94565b9396929550929360600135925050565b5f805f6060848603121561305a575f80fd5b833561306581612f94565b9250602084013561307581612f94565b9150604084013560028110613088575f80fd5b809150509250925092565b80356001600160601b03811681146130a9575f80fd5b919050565b5f80604083850312156130bf575f80fd5b612fdf83613093565b5f602082840312156130d8575f80fd5b5035919050565b5f602082840312156130ef575f80fd5b610c0f82613093565b602080825282518282018190525f9190848201906040850190845b818110156131385783516001600160a01b031683529284019291840191600101613113565b50909695505050505050565b5f8083601f840112613154575f80fd5b50813567ffffffffffffffff81111561316b575f80fd5b6020830191508360208260051b8501011115611622575f80fd5b5f805f8060408587031215613198575f80fd5b843567ffffffffffffffff808211156131af575f80fd5b6131bb88838901613144565b909650945060208701359150808211156131d3575f80fd5b506131e087828801613144565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61322c60608301866131ec565b931515602083015250901515604090910152919050565b5f8060408385031215613254575f80fd5b823561325f81612f94565b946020939093013593505050565b5f806020838503121561327e575f80fd5b823567ffffffffffffffff811115613294575f80fd5b6132a085828601613144565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b81811015613138578351835292840192918401916001016132c7565b5f805f606084860312156132f5575f80fd5b833561330081612f94565b9250602084013561331081612f94565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215613345575f80fd5b813567ffffffffffffffff8082111561335c575f80fd5b818401915084601f83011261336f575f80fd5b81358181111561338157613381613321565b604051601f8201601f19908116603f011681019083821181831017156133a9576133a9613321565b816040528281528760208487010111156133c1575f80fd5b826020860160208301375f928101602001929092525095945050505050565b8015158114612508575f80fd5b5f80604083850312156133fe575f80fd5b823561340981612f94565b91506020830135612fef816133e0565b5f806040838503121561342a575f80fd5b823561343581612f94565b9150602083013560098110612fef575f80fd5b5f8060408385031215613459575f80fd5b823561346481612f94565b915061347260208401613093565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156134a0575f80fd5b505080516020909101519092909150565b600281106134cd57634e487b7160e01b5f52602160045260245ffd5b9052565b602081016112b582846134b1565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061350757607f821691505b60208210810361352557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b5f600182016135505761355061352b565b5060010190565b5f6001600160601b038083168181036135725761357261352b565b6001019392505050565b601f82111561245657805f5260205f20601f840160051c810160208510156135a15750805b601f840160051c820191505b818110156135c0575f81556001016135ad565b5050505050565b815167ffffffffffffffff8111156135e1576135e1613321565b6135f5816135ef84546134f3565b8461357c565b602080601f831160018114613628575f84156136115750858301515b5f19600386901b1c1916600185901b178555611486565b5f85815260208120601f198616915b8281101561365657888601518255948401946001909101908401613637565b508582101561367357878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b602081525f610c0f60208301846131ec565b818103818111156112b5576112b561352b565b634e487b7160e01b5f52603160045260245ffd5b5f805f80608085870312156136cf575f80fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613713575f80fd5b5051919050565b6001600160a01b03831681526040602082018190525f90612c62908301846131ec565b5f6020828403121561374d575f80fd5b8151610c0f816133e0565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101611f6260a08301846134b1565b5f805f606084860312156137a5575f80fd5b835192506020840151915060408401519050925092509256fe616464506f6f6c4d61726b6574732875696e7439365b5d2c616464726573735b5d29a2646970667358221220bb3741952e77e5cd5b9ed84d8dc734611bb6edf887e2b22b9cdb301cd004f8ad64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061044d575f3560e01c806396c9906411610242578063cab4f84c11610140578063e0f6123d116100bf578063f02fdf9711610084578063f02fdf9714610b48578063f445d70314610b5b578063f851a44014610b88578063f968273214610b9a578063fa6331d814610bad575f80fd5b8063e0f6123d14610ac0578063e37d4b7914610ae2578063e85a296014610b19578063e875544614610b2c578063ede4edd014610b35575f80fd5b8063d585c3c611610105578063d585c3c614610a61578063d686e9ee14610a74578063dce1544914610a87578063dcfbc0c714610a9a578063ddbf54fd14610aad575f80fd5b8063cab4f84c1461088c578063d0d1303614610a21578063d137f36e14610a34578063d3270f9914610a47578063d463654c14610a5a575f80fd5b8063b8324c7c116101cc578063c299823811610191578063c29982381461099a578063c488847b146109ba578063c5b4db55146109cd578063c5f956af146109fb578063c7ee005e14610a0e575f80fd5b8063b8324c7c146108f3578063bb82aa5e1461094e578063bbb8864a14610961578063bec04f7214610980578063bf32442d14610989575f80fd5b8063a78dc77511610212578063a78dc7751461089f578063abfceffc146108b2578063afd3783b146108c5578063b0772d0b146108d8578063b2eafc39146108e0575f80fd5b806396c99064146108445780639bb27d6214610866578063a657e57914610879578063a76b3fda1461088c575f80fd5b80634a5844321161034f5780637d172bd5116102d95780638c1ac18a1161029e5780638c1ac18a146107e05780638e8f294b146108025780639254f5e514610815578063929fe9a11461082857806394b2294b1461083b575f80fd5b80637d172bd5146107795780637dc0d1d01461078c5780637fb8e8cd1461079f57806389c13be0146107ac5780638a7dc165146107c1575f80fd5b806363e0d6341161031f57806363e0d634146106eb578063719f701b1461070b578063737690991461071457806376551383146107545780637b86e42c14610766575f80fd5b80634a584432146106875780634d99c776146106a657806352d84d1e146106b95780635dd3fc9d146106cc575f80fd5b806321af4569116103db5780633093c11e116103a05780633093c11e146105d05780633d98a1e51461062a5780634088c73e1461063d57806341a18d2c1461064a578063425fad5814610674575f80fd5b806321af45691461054d578063236175851461057857806324a3d6221461058b578063267822471461059e5780632bc7e29e146105b1575f80fd5b806308e0225c1161042157806308e0225c146104b25780630db4b4e5146104dc5780630ef332ca146104e557806310b983381461050d57806319ef3e8b1461053a575f80fd5b80627e3dd21461045157806302c3bcbb1461046957806304ef9d58146104965780630686dab61461049f575b5f80fd5b60015b60405190151581526020015b60405180910390f35b610488610477366004612fa8565b60276020525f908152604090205481565b604051908152602001610460565b61048860225481565b6104886104ad366004612fa8565b610bb6565b6104886104c0366004612fc3565b601360209081525f928352604080842090915290825290205481565b610488601d5481565b6104f86104f3366004612ffa565b61107c565b60408051928352602083019190915201610460565b61045461051b366004612fc3565b602c60209081525f928352604080842090915290825290205460ff1681565b610488610548366004613048565b611119565b601e54610560906001600160a01b031681565b6040516001600160a01b039091168152602001610460565b610488610586366004612fa8565b6111ab565b600a54610560906001600160a01b031681565b600154610560906001600160a01b031681565b6104886105bf366004612fa8565b60166020525f908152604090205481565b6105e36105de3660046130ae565b6111c1565b604080519715158852602088019690965293151594860194909452606085019190915260808401526001600160601b0390911660a0830152151560c082015260e001610460565b610454610638366004612fa8565b611286565b6018546104549060ff1681565b610488610658366004612fc3565b601260209081525f928352604080842090915290825290205481565b6018546104549062010000900460ff1681565b610488610695366004612fa8565b601f6020525f908152604090205481565b6104886106b43660046130ae565b61129a565b6105606106c73660046130c8565b6112bb565b6104886106da366004612fa8565b602b6020525f908152604090205481565b6106fe6106f93660046130df565b6112e3565b60405161046091906130f8565b610488601c5481565b61073c610722366004612fa8565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610460565b60185461045490610100900460ff1681565b610488610774366004612fa8565b6113bc565b601b54610560906001600160a01b031681565b600454610560906001600160a01b031681565b6039546104549060ff1681565b6107bf6107ba366004613185565b6113d1565b005b6104886107cf366004612fa8565b60146020525f908152604090205481565b6104546107ee366004612fa8565b602d6020525f908152604090205460ff1681565b6105e3610810366004612fa8565b61148e565b601554610560906001600160a01b031681565b610454610836366004612fc3565b6114b6565b61048860075481565b6108576108523660046130df565b6114e5565b6040516104609392919061321a565b602554610560906001600160a01b031681565b60375461073c906001600160601b031681565b61048861089a366004612fa8565b611592565b6104f86108ad366004613243565b61159c565b6106fe6108c0366004612fa8565b611629565b6104886108d3366004612fc3565b611786565b6106fe6117bd565b602054610560906001600160a01b031681565b61092a610901366004612fa8565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610460565b600254610560906001600160a01b031681565b61048861096f366004612fa8565b602a6020525f908152604090205481565b61048860175481565b6033546001600160a01b0316610560565b6109ad6109a836600461326d565b61181d565b60405161046091906132ac565b6104f86109c83660046132e3565b6118d6565b6109e36ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b039091168152602001610460565b602154610560906001600160a01b031681565b603154610560906001600160a01b031681565b61073c610a2f366004613335565b61196a565b6107bf610a423660046130ae565b611a70565b602654610560906001600160a01b031681565b61073c5f81565b610488610a6f366004612fc3565b611cca565b610488610a82366004612fa8565b611d40565b610560610a95366004613243565b611d55565b600354610560906001600160a01b031681565b6107bf610abb3660046133ed565b611d89565b610454610ace366004612fa8565b60386020525f908152604090205460ff1681565b61092a610af0366004612fa8565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b610454610b27366004613419565b611e1b565b61048860055481565b610488610b43366004612fa8565b611e5f565b610454610b56366004613448565b612108565b610454610b69366004612fc3565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610560906001600160a01b031681565b6107bf610ba83660046130df565b612297565b610488601a5481565b5f610bed60405180604001604052806015815260200174756e6c6973744d61726b657428616464726573732960581b81525061245b565b5f610bf78361250b565b805490915060ff16610c1657610c0f6009601861252d565b9392505050565b610c21836002611e1b565b610c725760405162461bcd60e51b815260206004820152601b60248201527f626f72726f7720616374696f6e206973206e6f7420706175736564000000000060448201526064015b60405180910390fd5b610c7c835f611e1b565b610cc85760405162461bcd60e51b815260206004820152601960248201527f6d696e7420616374696f6e206973206e6f7420706175736564000000000000006044820152606401610c69565b610cd3836001611e1b565b610d1f5760405162461bcd60e51b815260206004820152601b60248201527f72656465656d20616374696f6e206973206e6f742070617573656400000000006044820152606401610c69565b610d2a836003611e1b565b610d765760405162461bcd60e51b815260206004820152601a60248201527f726570617920616374696f6e206973206e6f74207061757365640000000000006044820152606401610c69565b610d81836007611e1b565b610dd75760405162461bcd60e51b815260206004820152602160248201527f656e746572206d61726b657420616374696f6e206973206e6f742070617573656044820152601960fa1b6064820152608401610c69565b610de2836005611e1b565b610e2e5760405162461bcd60e51b815260206004820152601e60248201527f6c697175696461746520616374696f6e206973206e6f742070617573656400006044820152606401610c69565b610e39836004611e1b565b610e855760405162461bcd60e51b815260206004820152601a60248201527f7365697a6520616374696f6e206973206e6f74207061757365640000000000006044820152606401610c69565b610e90836006611e1b565b610edc5760405162461bcd60e51b815260206004820152601d60248201527f7472616e7366657220616374696f6e206973206e6f74207061757365640000006044820152606401610c69565b610ee7836008611e1b565b610f335760405162461bcd60e51b815260206004820181905260248201527f65786974206d61726b657420616374696f6e206973206e6f74207061757365646044820152606401610c69565b6001600160a01b0383165f908152601f602052604090205415610f8e5760405162461bcd60e51b81526020600482015260136024820152720626f72726f7720636170206973206e6f74203606c1b6044820152606401610c69565b6001600160a01b0383165f9081526027602052604090205415610fe95760405162461bcd60e51b81526020600482015260136024820152720737570706c7920636170206973206e6f74203606c1b6044820152606401610c69565b60018101541561103b5760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206973206e6f7420300000000000006044820152606401610c69565b805460ff191681556040516001600160a01b038416907f302feb03efd5741df80efe7f97f5d93d74d46a542a3d312d0faae64fa1f3e0e9905f90a25f610c0f565b602654604051630a5d5a0560e41b81526001600160a01b03868116600483015230602483015285811660448301528481166064830152608482018490525f92839283928392169063a5d5a0509060a4016040805180830381865afa1580156110e6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061110a919061348f565b90999098509650505050505050565b6001600160a01b0383165f9081526035602052604081205481908190611148906001600160601b0316866125a4565b5090925090505f8460018111156111615761116161347b565b0361116e57509050610c0f565b60018460018111156111825761118261347b565b03611190579150610c0f9050565b83604051632f03799f60e11b8152600401610c6991906134d1565b5f806111b75f846125a4565b5090949350505050565b5f805f805f805f60375f9054906101000a90046001600160601b03166001600160601b0316896001600160601b0316111561121a57604051632db8671b60e11b81526001600160601b038a166004820152602401610c69565b5f6112258a8a61129a565b5f9081526009602052604090208054600182015460038301546004840154600585015460069095015460ff9485169d50929b50908316995097509195506001600160601b0382169450600160601b9091041691505092959891949750929550565b5f6112908261250b565b5460ff1692915050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d81815481106112ca575f80fd5b5f918252602090912001546001600160a01b0316905081565b6037546060906001600160601b03908116908316111561132157604051632db8671b60e11b81526001600160601b0383166004820152602401610c69565b6001600160601b03821661134857604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f90815260366020908152604091829020600101805483518184028101840190945280845290918301828280156113b057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611392575b50505050509050919050565b5f806113c85f846125a4565b50949350505050565b6113f26040518060600160405280602281526020016137bf6022913961245b565b828015806114005750808214155b1561141e5760405163512509d360e11b815260040160405180910390fd5b5f5b818110156114865761147e86868381811061143d5761143d6134df565b905060200201602081019061145291906130df565b858584818110611464576114646134df565b90506020020160208101906114799190612fa8565b612656565b600101611420565b505050505050565b5f805f805f805f61149f5f896111c1565b959e949d50929b5090995097509550909350915050565b5f6114c08261250b565b6001600160a01b03939093165f90815260029093016020525050604090205460ff1690565b60366020525f90815260409020805481906114ff906134f3565b80601f016020809104026020016040519081016040528092919081815260200182805461152b906134f3565b80156115765780601f1061154d57610100808354040283529160200191611576565b820191905f5260205f20905b81548152906001019060200180831161155957829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6112b582612839565b6026546040516304f65f8b60e21b81523060048201526001600160a01b038481166024830152604482018490525f9283928392839216906313d97e2c906064016040805180830381865afa1580156115f6573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061161a919061348f565b909450925050505b9250929050565b6001600160a01b0381165f908152600860209081526040808320805482518185028101850190935280835260609493849392919083018282801561169457602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611676575b505050505090505f815190505f8167ffffffffffffffff8111156116ba576116ba613321565b6040519080825280602002602001820160405280156116e3578160200160208202803683370190505b5090505f5b82811015611779575f611713858381518110611706576117066134df565b602002602001015161250b565b805490915060ff161561177057848281518110611732576117326134df565b602002602001015183878151811061174c5761174c6134df565b6001600160a01b039092166020928302919091019091015261176d8661353f565b95505b506001016116e8565b5092835250909392505050565b6001600160a01b0382165f9081526035602052604081205481906117b3906001600160601b0316846125a4565b9695505050505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561181357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116117f5575b5050505050905090565b6060815f8167ffffffffffffffff81111561183a5761183a613321565b604051908082528060200260200182016040528015611863578160200160208202803683370190505b5090505f5b828110156113c8576118a0868683818110611885576118856134df565b905060200201602081019061189a9190612fa8565b3361296d565b60148111156118b1576118b161347b565b8282815181106118c3576118c36134df565b6020908102919091010152600101611868565b602654604051630779996560e11b81523060048201526001600160a01b0385811660248301528481166044830152606482018490525f928392839283921690630ef332ca906084016040805180830381865afa158015611938573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061195c919061348f565b909890975095505050505050565b5f61199e60405180604001604052806012815260200171637265617465506f6f6c28737472696e672960701b81525061245b565b81515f036119bf5760405163522e397360e11b815260040160405180910390fd5b603780545f919082906119da906001600160601b0316613557565b82546001600160601b038083166101009490940a848102910219909116179092555f90815260366020526040902090915080611a1685826135c7565b5060028101805460ff191660011790556040516001600160601b038316907fc419386a8582a5374f4db03fdbb9fd99c73ef32d6ce9fc3a8c249e97bf31f9af90611a61908790613683565b60405180910390a25092915050565b611aae6040518060400160405280602081526020017f72656d6f7665506f6f6c4d61726b65742875696e7439362c616464726573732981525061245b565b6001600160601b038216611ad557604051630203217b60e61b815260040160405180910390fd5b5f611ae0838361129a565b5f8181526009602052604090205490915060ff16611b2b576040516338ddb96b60e11b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c69565b6001600160601b0383165f908152603660205260408120600101805490915b81811015611c3857846001600160a01b0316838281548110611b6e57611b6e6134df565b5f918252602090912001546001600160a01b031603611c305782611b93600184613695565b81548110611ba357611ba36134df565b905f5260205f20015f9054906101000a90046001600160a01b0316838281548110611bd057611bd06134df565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480611c0b57611c0b6136a8565b5f8281526020902081015f1990810180546001600160a01b0319169055019055611c38565b600101611b4a565b505f83815260096020526040808220805460ff199081168255600182018490556003820180549091169055600481018390556005810183905560060180546cffffffffffffffffffffffffff19169055516001600160a01b038616916001600160601b038816917fc8bef274db6d8c804aba68a69e64268bcfe7dd0aead2efcec0cac73a2df56e129190a35050505050565b5f336001600160a01b03841614801590611d0757506001600160a01b0383165f908152602c6020908152604080832033845290915290205460ff16155b15611d25576040516337248ad960e01b815260040160405180910390fd5b611d2f828461296d565b6014811115610c0f57610c0f61347b565b5f80611d4c5f846125a4565b95945050505050565b6008602052815f5260405f208181548110611d6e575f80fd5b5f918252602090912001546001600160a01b03169150829050565b611d9282612a40565b335f908152602c602090815260408083206001600160a01b038616845290915290205481151560ff909116151503611e0c5760405162461bcd60e51b815260206004820152601b60248201527f44656c65676174696f6e2073746174757320756e6368616e67656400000000006044820152606401610c69565b611e17338383612a8e565b5050565b6001600160a01b0382165f90815260296020526040812081836008811115611e4557611e4561347b565b815260208101919091526040015f205460ff169392505050565b5f611e6b826008612afa565b6040516361bfb47160e11b815233600482015282905f90819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa158015611eb5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ed991906136bc565b50925092509250825f14611f2f5760405162461bcd60e51b815260206004820152601960248201527f6765744163636f756e74536e617073686f74206661696c6564000000000000006044820152606401610c69565b8015611f41576117b3600c600261252d565b5f611f4d873385612b44565b90508015611f6d57611f62600e600383612beb565b979650505050505050565b5f611f778661250b565b335f90815260028201602052604090205490915060ff16611f9f575f98975050505050505050565b335f9081526002820160209081526040808320805460ff1916905560089091528120805490915b818110156120b457886001600160a01b0316838281548110611fea57611fea6134df565b5f918252602090912001546001600160a01b0316036120ac578261200f600184613695565b8154811061201f5761201f6134df565b905f5260205f20015f9054906101000a90046001600160a01b031683828154811061204c5761204c6134df565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480612087576120876136a8565b5f8281526020902081015f1990810180546001600160a01b03191690550190556120b4565b600101611fc6565b8181106120c3576120c36136ef565b60405133906001600160a01b038b16907fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d905f90a35f9b9a5050505050505050505050565b6001600160a01b0382165f9081526008602090815260408083208054825181850281018501909352808352849383018282801561216c57602002820191905f5260205f20905b81546001600160a01b0316815260019091019060200180831161214e575b50939450505050506001600160601b038316158015906121a257506001600160a01b0384165f9081526016602052604090205415155b156121b0575f9150506112b5565b5f5b815181101561228c575f8282815181106121ce576121ce6134df565b602002602001015190505f6121e3868361129a565b5f81815260096020526040902060060154909150600160601b900460ff16612282576040516395dd919360e01b81526001600160a01b0388811660048301525f91908416906395dd919390602401602060405180830381865afa15801561224c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122709190613703565b1115612282575f9450505050506112b5565b50506001016121b2565b506001949350505050565b6037546001600160601b0390811690821611156122d257604051632db8671b60e11b81526001600160601b0382166004820152602401610c69565b335f908152603560205260409020546001600160601b039081169082160361230d57604051631c9d4f3960e31b815260040160405180910390fd5b6001600160601b0381161580159061234057506001600160601b0381165f9081526036602052604090206002015460ff16155b1561236957604051632da4cc0560e01b81526001600160601b0382166004820152602401610c69565b6123733382612108565b6123905760405163592ec11d60e01b815260040160405180910390fd5b335f818152603560209081526040918290205491516001600160601b03928316815291841692917f9181876220501cdac3aa7278fd34e9bd150c30a27b6ed95458fe859761b071f7910160405180910390a3335f81815260356020526040812080546bffffffffffffffffffffffff19166001600160601b03851617905590819061241b9082612c6a565b9250509150815f14158061242e57505f81115b156124565760405163c978466160e01b81526004810183905260248101829052604401610c69565b505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab9061248d903390859060040161371a565b602060405180830381865afa1580156124a8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906124cc919061373d565b6125085760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610c69565b50565b5f60095f6125195f8561129a565b81526020019081526020015f209050919050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360148111156125615761256161347b565b83601a8111156125735761257361347b565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610c0f57610c0f61347b565b6001600160601b0382165f818152603660205260408120909182918291829015806125d45750600282015460ff16155b156125e9576125e28661250b565b9050612638565b5f6125f4888861129a565b5f81815260096020526040902080549192509060ff1615801561262057506002840154610100900460ff165b61262a5780612633565b6126338861250b565b925050505b80600101548160040154826005015494509450945050509250925092565b6001600160601b03821661267d57604051630203217b60e61b815260040160405180910390fd5b6037546001600160601b0390811690831611156126b857604051632db8671b60e11b81526001600160601b0383166004820152602401610c69565b6001600160601b0382165f9081526036602052604090206002015460ff166126fe57604051632da4cc0560e01b81526001600160601b0383166004820152602401610c69565b5f6127095f8361129a565b5f8181526009602052604090205490915060ff1661273a576040516386dccab760e01b815260040160405180910390fd5b612744838361129a565b5f8181526009602052604090205490915060ff16156127905760405163d9d72f2b60e01b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c69565b5f8181526009602090815260408083206006810180546bffffffffffffffffffffffff19166001600160601b038916908117909155815460ff19166001908117835581865260368552838620810180549182018155865293852090930180546001600160a01b0319166001600160a01b038816908117909155915190939192917f2159e9508e372ac69e1047a124c5478445206066e5d7df7e4214a1986cd78c8091a350505050565b5f6128786040518060400160405280601781526020017f5f737570706f72744d61726b657428616464726573732900000000000000000081525061245b565b6128818261250b565b5460ff1615612896576112b5600a601161252d565b816001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa1580156128d2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906128f6919061373d565b505f6129018361250b565b8054600160ff19918216811783556003830180549092169091555f90820155905061292b83612ca2565b61293483612d78565b6040516001600160a01b038416907fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f905f90a25f610c0f565b5f612979836007612afa565b5f6129838461250b565b905061298e81612e3a565b6001600160a01b0383165f90815260028201602052604090205460ff16156129b9575f9150506112b5565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b6001600160a01b0381166125085760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610c69565b6001600160a01b038381165f818152602c6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fcb325b7784f78486e42849c7a50b8c5ee008d00cd90e108a58912c0fcb6288b4910160405180910390a3505050565b612b048282611e1b565b15611e175760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610c69565b5f612b56612b518561250b565b612e3a565b612b5f8461250b565b6001600160a01b0384165f908152600291909101602052604090205460ff16612b8957505f610c0f565b5f80612b988587865f80612e7f565b9193509091505f9050826014811115612bb357612bb361347b565b14612bd357816014811115612bca57612bca61347b565b92505050610c0f565b8015612be0576004612bca565b5f9695505050505050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846014811115612c1f57612c1f61347b565b84601a811115612c3157612c3161347b565b604080519283526020830191909152810184905260600160405180910390a1836014811115612c6257612c6261347b565b949350505050565b5f805f805f80612c7d885f805f8b612e7f565b925092509250826014811115612c9557612c9561347b565b9891975095509350505050565b600d545f5b81811015612d2557826001600160a01b0316600d8281548110612ccc57612ccc6134df565b5f918252602090912001546001600160a01b031603612d1d5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481859191959609a1b6044820152606401610c69565b600101612ca7565b5050600d80546001810182555f919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b5f612d81612f2c565b6001600160a01b0383165f908152601060209081526040808320601190925282208154939450909290916001600160e01b039091169003612ddc5781546001600160e01b0319166ec097ce7bc90715b34b9f10000000001782555b80546001600160e01b03165f03612e0d5780546001600160e01b0319166ec097ce7bc90715b34b9f10000000001781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b805460ff166125085760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610c69565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e90612ec59030908f908f908f908f908f90600401613758565b606060405180830381865afa158015612ee0573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f049190613793565b925092509250826014811115612f1c57612f1c61347b565b9b919a5098509650505050505050565b5f612f604360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612f65565b905090565b5f816401000000008410612f8c5760405162461bcd60e51b8152600401610c699190613683565b509192915050565b6001600160a01b0381168114612508575f80fd5b5f60208284031215612fb8575f80fd5b8135610c0f81612f94565b5f8060408385031215612fd4575f80fd5b8235612fdf81612f94565b91506020830135612fef81612f94565b809150509250929050565b5f805f806080858703121561300d575f80fd5b843561301881612f94565b9350602085013561302881612f94565b9250604085013561303881612f94565b9396929550929360600135925050565b5f805f6060848603121561305a575f80fd5b833561306581612f94565b9250602084013561307581612f94565b9150604084013560028110613088575f80fd5b809150509250925092565b80356001600160601b03811681146130a9575f80fd5b919050565b5f80604083850312156130bf575f80fd5b612fdf83613093565b5f602082840312156130d8575f80fd5b5035919050565b5f602082840312156130ef575f80fd5b610c0f82613093565b602080825282518282018190525f9190848201906040850190845b818110156131385783516001600160a01b031683529284019291840191600101613113565b50909695505050505050565b5f8083601f840112613154575f80fd5b50813567ffffffffffffffff81111561316b575f80fd5b6020830191508360208260051b8501011115611622575f80fd5b5f805f8060408587031215613198575f80fd5b843567ffffffffffffffff808211156131af575f80fd5b6131bb88838901613144565b909650945060208701359150808211156131d3575f80fd5b506131e087828801613144565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61322c60608301866131ec565b931515602083015250901515604090910152919050565b5f8060408385031215613254575f80fd5b823561325f81612f94565b946020939093013593505050565b5f806020838503121561327e575f80fd5b823567ffffffffffffffff811115613294575f80fd5b6132a085828601613144565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b81811015613138578351835292840192918401916001016132c7565b5f805f606084860312156132f5575f80fd5b833561330081612f94565b9250602084013561331081612f94565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215613345575f80fd5b813567ffffffffffffffff8082111561335c575f80fd5b818401915084601f83011261336f575f80fd5b81358181111561338157613381613321565b604051601f8201601f19908116603f011681019083821181831017156133a9576133a9613321565b816040528281528760208487010111156133c1575f80fd5b826020860160208301375f928101602001929092525095945050505050565b8015158114612508575f80fd5b5f80604083850312156133fe575f80fd5b823561340981612f94565b91506020830135612fef816133e0565b5f806040838503121561342a575f80fd5b823561343581612f94565b9150602083013560098110612fef575f80fd5b5f8060408385031215613459575f80fd5b823561346481612f94565b915061347260208401613093565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156134a0575f80fd5b505080516020909101519092909150565b600281106134cd57634e487b7160e01b5f52602160045260245ffd5b9052565b602081016112b582846134b1565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061350757607f821691505b60208210810361352557634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b5f600182016135505761355061352b565b5060010190565b5f6001600160601b038083168181036135725761357261352b565b6001019392505050565b601f82111561245657805f5260205f20601f840160051c810160208510156135a15750805b601f840160051c820191505b818110156135c0575f81556001016135ad565b5050505050565b815167ffffffffffffffff8111156135e1576135e1613321565b6135f5816135ef84546134f3565b8461357c565b602080601f831160018114613628575f84156136115750858301515b5f19600386901b1c1916600185901b178555611486565b5f85815260208120601f198616915b8281101561365657888601518255948401946001909101908401613637565b508582101561367357878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b602081525f610c0f60208301846131ec565b818103818111156112b5576112b561352b565b634e487b7160e01b5f52603160045260245ffd5b5f805f80608085870312156136cf575f80fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b5f52600160045260245ffd5b5f60208284031215613713575f80fd5b5051919050565b6001600160a01b03831681526040602082018190525f90612c62908301846131ec565b5f6020828403121561374d575f80fd5b8151610c0f816133e0565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101611f6260a08301846134b1565b5f805f606084860312156137a5575f80fd5b835192506020840151915060408401519050925092509256fe616464506f6f6c4d61726b6574732875696e7439365b5d2c616464726573735b5d29a2646970667358221220bb3741952e77e5cd5b9ed84d8dc734611bb6edf887e2b22b9cdb301cd004f8ad64736f6c63430008190033", + "numDeployments": 2, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"approver\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"DelegateUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketExited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketListed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketUnlisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"PoolCreated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"PoolMarketInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketRemoved\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint96\",\"name\":\"previousPoolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"newPoolId\",\"type\":\"uint96\"}],\"name\":\"PoolSelected\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"_supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96[]\",\"name\":\"poolIds\",\"type\":\"uint96[]\"},{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"addPoolMarkets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"checkMembership\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"}],\"name\":\"createPool\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"onBehalf\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"enterMarketBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"enterMarkets\",\"outputs\":[{\"internalType\":\"uint256[]\",\"name\":\"\",\"type\":\"uint256[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"enterPool\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"}],\"name\":\"exitMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getAllMarkets\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAssetsIn\",\"outputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getEffectiveLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"enum WeightFunction\",\"name\":\"weightingStrategy\",\"type\":\"uint8\"}],\"name\":\"getEffectiveLtvFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getLiquidationThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"getPoolVTokens\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"targetPoolId\",\"type\":\"uint96\"}],\"name\":\"hasValidPoolBorrows\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isComptroller\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"isMarketListed\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateCalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateVAICalculateSeizeTokens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"markets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isVenus\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"marketPoolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"isBorrowAllowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"poolMarkets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"isListed\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"collateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isVenus\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"liquidationThresholdMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"liquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint96\",\"name\":\"marketPoolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"isBorrowAllowed\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"removePoolMarket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"supportMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"unlistMarket\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"delegate\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"updateDelegate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the methods related to the market's management in the pool\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_supportMarket(address)\":{\"details\":\"Allows a privileged role to add and list markets to the Comptroller\",\"params\":{\"vToken\":\"The address of the vToken market to list in the Core Pool\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"addPoolMarkets(uint96[],address[])\":{\"custom:error\":\"ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.MarketNotListedInCorePool Reverts if the market is not listed in the core pool.MarketAlreadyListed Reverts if the given market is already listed in the specified pool.InactivePool Reverts if attempted to add markets to an inactive pool.\",\"custom:event\":\"PoolMarketInitialized Emitted after successfully initializing a market in a pool.\",\"params\":{\"poolIds\":\"Array of pool IDs.\",\"vTokens\":\"Array of market (vToken) addresses.\"}},\"checkMembership(address,address)\":{\"details\":\"Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools, all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\",\"params\":{\"account\":\"The address of the account to check\",\"vToken\":\"The vToken to check\"},\"returns\":{\"_0\":\"True if the account is in the asset, otherwise false\"}},\"createPool(string)\":{\"custom:error\":\"EmptyPoolLabel Reverts if the provided label is an empty string.\",\"custom:event\":\"PoolCreated Emitted after successfully creating a new pool.\",\"params\":{\"label\":\"name for the pool (must be non-empty).\"},\"returns\":{\"_0\":\"poolId The incremental unique identifier of the newly created pool.\"}},\"enterMarketBehalf(address,address)\":{\"custom:error\":\"NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\",\"details\":\"Only callable by the account itself or an approved delegate\",\"params\":{\"onBehalf\":\"The address of the account entering the market\",\"vToken\":\"The address of the vToken market to enable for the account\"},\"returns\":{\"_0\":\"uint256 indicating the result (0 = success, non-zero = failure)\"}},\"enterMarkets(address[])\":{\"params\":{\"vTokens\":\"The list of addresses of the vToken markets to be enabled\"},\"returns\":{\"_0\":\"Success indicator for whether each corresponding market was entered\"}},\"enterPool(uint96)\":{\"custom:error\":\"PoolDoesNotExist The specified pool ID does not exist.AlreadyInSelectedPool The user is already in the target pool.IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.LiquidityCheckFailed The user's liquidity is insufficient after switching pools.InactivePool The user is trying to enter inactive pool.\",\"custom:event\":\"PoolSelected Emitted after a successful pool switch.\",\"params\":{\"poolId\":\"The ID of the pool the user wants to enter.\"}},\"exitMarket(address)\":{\"details\":\"Sender must not have an outstanding borrow balance in the asset, or be providing necessary collateral for an outstanding borrow\",\"params\":{\"vTokenAddress\":\"The address of the asset to be removed\"},\"returns\":{\"_0\":\"Whether or not the account successfully exited the market\"}},\"getAllMarkets()\":{\"details\":\"The automatic getter may be used to access an individual market\",\"returns\":{\"_0\":\"The list of market addresses\"}},\"getAssetsIn(address)\":{\"details\":\"Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools, all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\",\"params\":{\"account\":\"The address of the account to query\"},\"returns\":{\"_0\":\"assets A dynamic array of vToken markets the account has entered\"}},\"getCollateralFactor(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the collateral factor for\"},\"returns\":{\"_0\":\"The collateral factor for the vToken, scaled by 1e18\"}},\"getEffectiveLiquidationIncentive(address,address)\":{\"details\":\"The incentive is determined by the pool entered by the account and the specified vToken via `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\",\"params\":{\"account\":\"The account whose pool is used to determine the market's risk parameters\",\"vToken\":\"The address of the vToken market\"},\"returns\":{\"_0\":\"The liquidation Incentive for the vToken, scaled by 1e18\"}},\"getEffectiveLtvFactor(address,address,uint8)\":{\"details\":\"The value is determined by the pool entered by the account and the specified vToken via `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used. This value is used for account liquidity calculations and liquidation checks.\",\"params\":{\"account\":\"The account whose pool is used to determine the market's risk parameters.\",\"vToken\":\"The address of the vToken market.\",\"weightingStrategy\":\"The weighting strategy to use: - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\"},\"returns\":{\"_0\":\"factor The effective loan-to-value factor, scaled by 1e18.\"}},\"getLiquidationIncentive(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the liquidation Incentive for\"},\"returns\":{\"_0\":\"liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\"}},\"getLiquidationThreshold(address)\":{\"params\":{\"vToken\":\"The address of the vToken to get the liquidation threshold for\"},\"returns\":{\"_0\":\"The liquidation threshold for the vToken, scaled by 1e18\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getPoolVTokens(uint96)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the given pool ID do not exist.InvalidOperationForCorePool Reverts if called on the Core Pool.\",\"params\":{\"poolId\":\"The ID of the pool whose vTokens are being queried.\"},\"returns\":{\"_0\":\"An array of vToken addresses associated with the pool.\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"hasValidPoolBorrows(address,uint96)\":{\"params\":{\"account\":\"The address of the user attempting to switch pools.\",\"targetPoolId\":\"The pool ID the user wants to switch into.\"},\"returns\":{\"_0\":\"bool True if the switch is allowed, otherwise False.\"}},\"isMarketListed(address)\":{\"params\":{\"vToken\":\"The vToken Address of the market to check\"},\"returns\":{\"_0\":\"listed True if the (Core Pool, vToken) market is listed, otherwise false\"}},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"borrower\":\"Address of borrower whose collateral is being seized\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenBorrowed\":\"The address of the borrowed vToken\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"liquidateVAICalculateSeizeTokens(address,uint256)\":{\"details\":\"Used in liquidation (called in vToken.liquidateBorrowFresh)\",\"params\":{\"actualRepayAmount\":\"The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\",\"vTokenCollateral\":\"The address of the collateral vToken\"},\"returns\":{\"_0\":\"(errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\"}},\"markets(address)\":{\"details\":\"Fetches the Market struct associated with the core pool and returns all relevant parameters.\",\"params\":{\"vToken\":\"The address of the vToken whose market configuration is to be fetched.\"},\"returns\":{\"collateralFactorMantissa\":\"The maximum borrowable percentage of collateral, in mantissa.\",\"isBorrowAllowed\":\"Whether borrowing is allowed in this market.\",\"isListed\":\"Whether the market is listed and enabled.\",\"isVenus\":\"Whether this market is eligible for VENUS rewards.\",\"liquidationIncentiveMantissa\":\"The max liquidation incentive allowed for this market, in mantissa.\",\"liquidationThresholdMantissa\":\"The threshold at which liquidation is triggered, in mantissa.\",\"marketPoolId\":\"The pool ID this market belongs to.\"}},\"poolMarkets(uint96,address)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the given pool ID do not exist.\",\"details\":\"Fetches the Market struct associated with the poolId and returns all relevant parameters.\",\"params\":{\"poolId\":\"The ID of the pool whose market configuration is being queried.\",\"vToken\":\"The address of the vToken whose market configuration is to be fetched.\"},\"returns\":{\"collateralFactorMantissa\":\"The maximum borrowable percentage of collateral, in mantissa.\",\"isBorrowAllowed\":\"Whether borrowing is allowed in this market.\",\"isListed\":\"Whether the market is listed and enabled.\",\"isVenus\":\"Whether this market is eligible for XVS rewards.\",\"liquidationIncentiveMantissa\":\"The liquidation incentive allowed for this market, in mantissa.\",\"liquidationThresholdMantissa\":\"The threshold at which liquidation is triggered, in mantissa.\",\"marketPoolId\":\"The pool ID this market belongs to.\"}},\"removePoolMarket(uint96,address)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts if called on the Core Pool.PoolMarketNotFound Reverts if the market is not listed in the pool.\",\"custom:event\":\"PoolMarketRemoved Emitted after a market is successfully removed from a pool.\",\"params\":{\"poolId\":\"The ID of the pool from which the market should be removed.\",\"vToken\":\"The address of the market token to remove.\"}},\"supportMarket(address)\":{\"params\":{\"vToken\":\"The address of the market (token) to list\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"unlistMarket(address)\":{\"details\":\"Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\",\"params\":{\"market\":\"The address of the market (vToken) to unlist\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (See enum Error for details)\"}},\"updateDelegate(address,bool)\":{\"params\":{\"approved\":\"Whether to grant (true) or revoke (false) the borrowing or redeeming rights\",\"delegate\":\"The address to update the rights for\"}}},\"title\":\"MarketFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DelegateUpdated(address,address,bool)\":{\"notice\":\"Emitted when the borrowing or redeeming delegate rights are updated for an account\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"MarketExited(address,address)\":{\"notice\":\"Emitted when an account exits a market\"},\"MarketListed(address)\":{\"notice\":\"Emitted when an admin supports a market\"},\"MarketUnlisted(address)\":{\"notice\":\"Emitted when an admin unlists a market\"},\"PoolCreated(uint96,string)\":{\"notice\":\"Emitted when a new pool is created\"},\"PoolMarketInitialized(uint96,address)\":{\"notice\":\"Emitted when a market is initialized in a pool\"},\"PoolMarketRemoved(uint96,address)\":{\"notice\":\"Emitted when a vToken market is removed from a pool\"},\"PoolSelected(address,uint96,uint96)\":{\"notice\":\"Emitted when a user enters or exits a pool (poolId = 0 means exit)\"}},\"kind\":\"user\",\"methods\":{\"_supportMarket(address)\":{\"notice\":\"Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"addPoolMarkets(uint96[],address[])\":{\"notice\":\"Batch initializes market entries with basic config.\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"checkMembership(address,address)\":{\"notice\":\"Returns whether the given account has entered the specified vToken market in the Core Pool\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"createPool(string)\":{\"notice\":\"Creates a new pool with the given label.\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"enterMarketBehalf(address,address)\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"enterMarkets(address[])\":{\"notice\":\"Add assets to be included in account liquidity calculation\"},\"enterPool(uint96)\":{\"notice\":\"Allows a user to switch to a new pool (e.g., e-mode ).\"},\"exitMarket(address)\":{\"notice\":\"Removes asset from sender's account liquidity calculation\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getAllMarkets()\":{\"notice\":\"Return all of the markets\"},\"getAssetsIn(address)\":{\"notice\":\"Returns the vToken markets an account has entered in the Core Pool\"},\"getCollateralFactor(address)\":{\"notice\":\"Get the core pool collateral factor for a vToken\"},\"getEffectiveLiquidationIncentive(address,address)\":{\"notice\":\"Get the Effective Liquidation Incentive for a given account and market\"},\"getEffectiveLtvFactor(address,address,uint8)\":{\"notice\":\"Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\"},\"getLiquidationIncentive(address)\":{\"notice\":\"Get the core pool liquidation Incentive for a vToken\"},\"getLiquidationThreshold(address)\":{\"notice\":\"Get the core pool liquidation threshold for a vToken\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getPoolVTokens(uint96)\":{\"notice\":\"Returns the full list of vTokens for a given pool ID.\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"hasValidPoolBorrows(address,uint96)\":{\"notice\":\"Returns true if the user can switch to the given target pool, i.e., all markets they have borrowed from are also borrowable in the target pool.\"},\"isComptroller()\":{\"notice\":\"Indicator that this is a Comptroller contract (for inspection)\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"isMarketListed(address)\":{\"notice\":\"Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"liquidateCalculateSeizeTokens(address,address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidateCalculateSeizeTokens(address,address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"liquidateVAICalculateSeizeTokens(address,uint256)\":{\"notice\":\"Calculate number of tokens of collateral asset to seize given an underlying amount\"},\"markets(address)\":{\"notice\":\"Returns the market configuration for a vToken in the core pool (poolId = 0).\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"poolMarkets(uint96,address)\":{\"notice\":\"Returns the market configuration for a vToken from _poolMarkets.\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"removePoolMarket(uint96,address)\":{\"notice\":\"Removes a market (vToken) from the specified pool.\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"supportMarket(address)\":{\"notice\":\"Alias to _supportMarket to support the Isolated Lending Comptroller Interface\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"unlistMarket(address)\":{\"notice\":\"Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\"},\"updateDelegate(address,bool)\":{\"notice\":\"Grants or revokes the borrowing or redeeming delegate rights to / from an account If allowed, the delegate will be able to borrow funds on behalf of the sender Upon a delegated borrow, the delegate will receive the funds, and the borrower will see the debt on their account Upon a delegated redeem, the delegate will receive the redeemed amount and the approver will see a deduction in his vToken balance\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains functions regarding markets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/MarketFacet.sol\":\"MarketFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/MarketFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IMarketFacet } from \\\"../interfaces/IMarketFacet.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title MarketFacet\\n * @author Venus\\n * @dev This facet contains all the methods related to the market's management in the pool\\n * @notice This facet contract contains functions regarding markets\\n */\\ncontract MarketFacet is IMarketFacet, FacetBase {\\n /// @notice Emitted when an admin supports a market\\n event MarketListed(VToken indexed vToken);\\n\\n /// @notice Emitted when an account exits a market\\n event MarketExited(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account\\n event DelegateUpdated(address indexed approver, address indexed delegate, bool approved);\\n\\n /// @notice Emitted when an admin unlists a market\\n event MarketUnlisted(address indexed vToken);\\n\\n /// @notice Emitted when a market is initialized in a pool\\n event PoolMarketInitialized(uint96 indexed poolId, address indexed market);\\n\\n /// @notice Emitted when a user enters or exits a pool (poolId = 0 means exit)\\n event PoolSelected(address indexed account, uint96 previousPoolId, uint96 indexed newPoolId);\\n\\n /// @notice Emitted when a vToken market is removed from a pool\\n event PoolMarketRemoved(uint96 indexed poolId, address indexed vToken);\\n\\n /// @notice Emitted when a new pool is created\\n event PoolCreated(uint96 indexed poolId, string label);\\n\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() public pure returns (bool) {\\n return true;\\n }\\n\\n /**\\n * @notice Returns the vToken markets an account has entered in the Core Pool\\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\\n * @param account The address of the account to query\\n * @return assets A dynamic array of vToken markets the account has entered\\n */\\n function getAssetsIn(address account) external view returns (VToken[] memory) {\\n uint256 len;\\n VToken[] memory _accountAssets = accountAssets[account];\\n uint256 _accountAssetsLength = _accountAssets.length;\\n\\n VToken[] memory assetsIn = new VToken[](_accountAssetsLength);\\n\\n for (uint256 i; i < _accountAssetsLength; ++i) {\\n Market storage market = getCorePoolMarket(address(_accountAssets[i]));\\n if (market.isListed) {\\n assetsIn[len] = _accountAssets[i];\\n ++len;\\n }\\n }\\n\\n assembly {\\n mstore(assetsIn, len)\\n }\\n\\n return assetsIn;\\n }\\n\\n /**\\n * @notice Return all of the markets\\n * @dev The automatic getter may be used to access an individual market\\n * @return The list of market addresses\\n */\\n function getAllMarkets() external view returns (VToken[] memory) {\\n return allMarkets;\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\\n address(this),\\n vTokenBorrowed,\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param borrower Address of borrower whose collateral is being seized\\n * @param vTokenBorrowed The address of the borrowed vToken\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n vTokenBorrowed,\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\\n * @param vTokenCollateral The address of the collateral vToken\\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\\n */\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256) {\\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\\n address(this),\\n vTokenCollateral,\\n actualRepayAmount\\n );\\n return (err, seizeTokens);\\n }\\n\\n /**\\n * @notice Returns whether the given account has entered the specified vToken market in the Core Pool\\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\\n * @param account The address of the account to check\\n * @param vToken The vToken to check\\n * @return True if the account is in the asset, otherwise false\\n */\\n function checkMembership(address account, VToken vToken) external view returns (bool) {\\n return getCorePoolMarket(address(vToken)).accountMembership[account];\\n }\\n\\n /**\\n * @notice Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken Address of the market to check\\n * @return listed True if the (Core Pool, vToken) market is listed, otherwise false\\n */\\n function isMarketListed(VToken vToken) external view returns (bool) {\\n return getCorePoolMarket(address(vToken)).isListed;\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @param vTokens The list of addresses of the vToken markets to be enabled\\n * @return Success indicator for whether each corresponding market was entered\\n */\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\\n uint256 len = vTokens.length;\\n\\n uint256[] memory results = new uint256[](len);\\n for (uint256 i; i < len; ++i) {\\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\\n }\\n\\n return results;\\n }\\n\\n /**\\n * @notice Add assets to be included in account liquidity calculation\\n * @dev Only callable by the account itself or an approved delegate\\n * @param onBehalf The address of the account entering the market\\n * @param vToken The address of the vToken market to enable for the account\\n * @return uint256 indicating the result (0 = success, non-zero = failure)\\n * @custom:error NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\\n */\\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256) {\\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\\n revert NotAnApprovedDelegate();\\n }\\n return uint256(addToMarketInternal(VToken(vToken), onBehalf));\\n }\\n\\n /**\\n * @notice Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\\n * @dev Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\\n * @param market The address of the market (vToken) to unlist\\n * @return uint256 0=success, otherwise a failure (See enum Error for details)\\n */\\n function unlistMarket(address market) external returns (uint256) {\\n ensureAllowed(\\\"unlistMarket(address)\\\");\\n\\n Market storage _market = getCorePoolMarket(market);\\n\\n if (!_market.isListed) {\\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.UNLIST_MARKET_NOT_LISTED);\\n }\\n\\n require(actionPaused(market, Action.BORROW), \\\"borrow action is not paused\\\");\\n require(actionPaused(market, Action.MINT), \\\"mint action is not paused\\\");\\n require(actionPaused(market, Action.REDEEM), \\\"redeem action is not paused\\\");\\n require(actionPaused(market, Action.REPAY), \\\"repay action is not paused\\\");\\n require(actionPaused(market, Action.ENTER_MARKET), \\\"enter market action is not paused\\\");\\n require(actionPaused(market, Action.LIQUIDATE), \\\"liquidate action is not paused\\\");\\n require(actionPaused(market, Action.SEIZE), \\\"seize action is not paused\\\");\\n require(actionPaused(market, Action.TRANSFER), \\\"transfer action is not paused\\\");\\n require(actionPaused(market, Action.EXIT_MARKET), \\\"exit market action is not paused\\\");\\n\\n require(borrowCaps[market] == 0, \\\"borrow cap is not 0\\\");\\n require(supplyCaps[market] == 0, \\\"supply cap is not 0\\\");\\n\\n require(_market.collateralFactorMantissa == 0, \\\"collateral factor is not 0\\\");\\n\\n _market.isListed = false;\\n emit MarketUnlisted(market);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Removes asset from sender's account liquidity calculation\\n * @dev Sender must not have an outstanding borrow balance in the asset,\\n * or be providing necessary collateral for an outstanding borrow\\n * @param vTokenAddress The address of the asset to be removed\\n * @return Whether or not the account successfully exited the market\\n */\\n function exitMarket(address vTokenAddress) external returns (uint256) {\\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\\n\\n VToken vToken = VToken(vTokenAddress);\\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\\n require(oErr == 0, \\\"getAccountSnapshot failed\\\"); // semi-opaque error code\\n\\n /* Fail if the sender has a borrow balance */\\n if (amountOwed != 0) {\\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\\n }\\n\\n /* Fail if the sender is not permitted to redeem all of their tokens */\\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\\n if (allowed != 0) {\\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\\n }\\n\\n Market storage marketToExit = getCorePoolMarket(address(vToken));\\n\\n /* Return true if the sender is not already \\u2018in\\u2019 the market */\\n if (!marketToExit.accountMembership[msg.sender]) {\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /* Set vToken account membership to false */\\n delete marketToExit.accountMembership[msg.sender];\\n\\n /* Delete vToken from the account\\u2019s list of assets */\\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\\n VToken[] storage userAssetList = accountAssets[msg.sender];\\n uint256 len = userAssetList.length;\\n uint256 i;\\n for (; i < len; ++i) {\\n if (userAssetList[i] == vToken) {\\n userAssetList[i] = userAssetList[len - 1];\\n userAssetList.pop();\\n break;\\n }\\n }\\n\\n // We *must* have found the asset in the list or our redundant data structure is broken\\n assert(i < len);\\n\\n emit MarketExited(vToken, msg.sender);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Alias to _supportMarket to support the Isolated Lending Comptroller Interface\\n * @param vToken The address of the market (token) to list\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function supportMarket(VToken vToken) external returns (uint256) {\\n return __supportMarket(vToken);\\n }\\n\\n /**\\n * @notice Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\\n * @dev Allows a privileged role to add and list markets to the Comptroller\\n * @param vToken The address of the vToken market to list in the Core Pool\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _supportMarket(VToken vToken) external returns (uint256) {\\n return __supportMarket(vToken);\\n }\\n\\n /**\\n * @notice Grants or revokes the borrowing or redeeming delegate rights to / from an account\\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\\n * will see the debt on their account\\n * Upon a delegated redeem, the delegate will receive the redeemed amount and the approver\\n * will see a deduction in his vToken balance\\n * @param delegate The address to update the rights for\\n * @param approved Whether to grant (true) or revoke (false) the borrowing or redeeming rights\\n */\\n function updateDelegate(address delegate, bool approved) external {\\n ensureNonzeroAddress(delegate);\\n require(approvedDelegates[msg.sender][delegate] != approved, \\\"Delegation status unchanged\\\");\\n\\n _updateDelegate(msg.sender, delegate, approved);\\n }\\n\\n /**\\n * @notice Allows a user to switch to a new pool (e.g., e-mode ).\\n * @param poolId The ID of the pool the user wants to enter.\\n * @custom:error PoolDoesNotExist The specified pool ID does not exist.\\n * @custom:error AlreadyInSelectedPool The user is already in the target pool.\\n * @custom:error IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.\\n * @custom:error LiquidityCheckFailed The user's liquidity is insufficient after switching pools.\\n * @custom:error InactivePool The user is trying to enter inactive pool.\\n * @custom:event PoolSelected Emitted after a successful pool switch.\\n */\\n function enterPool(uint96 poolId) external {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n if (poolId == userPoolId[msg.sender]) {\\n revert AlreadyInSelectedPool();\\n }\\n\\n if (poolId != corePoolId && !pools[poolId].isActive) {\\n revert InactivePool(poolId);\\n }\\n\\n if (!hasValidPoolBorrows(msg.sender, poolId)) {\\n revert IncompatibleBorrowedAssets();\\n }\\n\\n emit PoolSelected(msg.sender, userPoolId[msg.sender], poolId);\\n\\n userPoolId[msg.sender] = poolId;\\n\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n msg.sender,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR || shortfall > 0) {\\n revert LiquidityCheckFailed(uint256(err), shortfall);\\n }\\n }\\n\\n /**\\n * @notice Creates a new pool with the given label.\\n * @param label name for the pool (must be non-empty).\\n * @return poolId The incremental unique identifier of the newly created pool.\\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string.\\n * @custom:event PoolCreated Emitted after successfully creating a new pool.\\n */\\n function createPool(string memory label) external returns (uint96) {\\n ensureAllowed(\\\"createPool(string)\\\");\\n\\n if (bytes(label).length == 0) {\\n revert EmptyPoolLabel();\\n }\\n\\n uint96 poolId = ++lastPoolId;\\n PoolData storage newPool = pools[poolId];\\n newPool.label = label;\\n newPool.isActive = true;\\n\\n emit PoolCreated(poolId, label);\\n return poolId;\\n }\\n\\n /**\\n * @notice Batch initializes market entries with basic config.\\n * @param poolIds Array of pool IDs.\\n * @param vTokens Array of market (vToken) addresses.\\n * @custom:error ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:error MarketNotListedInCorePool Reverts if the market is not listed in the core pool.\\n * @custom:error MarketAlreadyListed Reverts if the given market is already listed in the specified pool.\\n * @custom:error InactivePool Reverts if attempted to add markets to an inactive pool.\\n * @custom:event PoolMarketInitialized Emitted after successfully initializing a market in a pool.\\n */\\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external {\\n ensureAllowed(\\\"addPoolMarkets(uint96[],address[])\\\");\\n\\n uint256 len = poolIds.length;\\n if (len == 0 || len != vTokens.length) {\\n revert ArrayLengthMismatch();\\n }\\n\\n for (uint256 i; i < len; i++) {\\n _addPoolMarket(poolIds[i], vTokens[i]);\\n }\\n }\\n\\n /**\\n * @notice Removes a market (vToken) from the specified pool.\\n * @param poolId The ID of the pool from which the market should be removed.\\n * @param vToken The address of the market token to remove.\\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\\n * @custom:error PoolMarketNotFound Reverts if the market is not listed in the pool.\\n * @custom:event PoolMarketRemoved Emitted after a market is successfully removed from a pool.\\n */\\n function removePoolMarket(uint96 poolId, address vToken) external {\\n ensureAllowed(\\\"removePoolMarket(uint96,address)\\\");\\n\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\\n if (!_poolMarkets[index].isListed) {\\n revert PoolMarketNotFound(poolId, vToken);\\n }\\n\\n address[] storage assets = pools[poolId].vTokens;\\n\\n uint256 length = assets.length;\\n for (uint256 i; i < length; i++) {\\n if (assets[i] == vToken) {\\n assets[i] = assets[length - 1];\\n assets.pop();\\n break;\\n }\\n }\\n\\n delete _poolMarkets[index];\\n\\n emit PoolMarketRemoved(poolId, vToken);\\n }\\n\\n /**\\n * @notice Get the core pool collateral factor for a vToken\\n * @param vToken The address of the vToken to get the collateral factor for\\n * @return The collateral factor for the vToken, scaled by 1e18\\n */\\n function getCollateralFactor(address vToken) external view returns (uint256) {\\n (uint256 cf, , ) = getLiquidationParams(corePoolId, vToken);\\n return cf;\\n }\\n\\n /**\\n * @notice Get the core pool liquidation threshold for a vToken\\n * @param vToken The address of the vToken to get the liquidation threshold for\\n * @return The liquidation threshold for the vToken, scaled by 1e18\\n */\\n function getLiquidationThreshold(address vToken) external view returns (uint256) {\\n (, uint256 lt, ) = getLiquidationParams(corePoolId, vToken);\\n return lt;\\n }\\n\\n /**\\n * @notice Get the core pool liquidation Incentive for a vToken\\n * @param vToken The address of the vToken to get the liquidation Incentive for\\n * @return liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\\n */\\n function getLiquidationIncentive(address vToken) external view returns (uint256) {\\n (, , uint256 li) = getLiquidationParams(corePoolId, vToken);\\n return li;\\n }\\n\\n /**\\n * @notice Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\\n * @dev The value is determined by the pool entered by the account and the specified vToken via\\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used.\\n * This value is used for account liquidity calculations and liquidation checks.\\n * @param account The account whose pool is used to determine the market's risk parameters.\\n * @param vToken The address of the vToken market.\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return factor The effective loan-to-value factor, scaled by 1e18.\\n */\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256) {\\n (uint256 cf, uint256 lt, ) = getLiquidationParams(userPoolId[account], vToken);\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) return cf;\\n else if (weightingStrategy == WeightFunction.USE_LIQUIDATION_THRESHOLD) return lt;\\n else revert InvalidWeightingStrategy(weightingStrategy);\\n }\\n\\n /**\\n * @notice Get the Effective Liquidation Incentive for a given account and market\\n * @dev The incentive is determined by the pool entered by the account and the specified vToken via\\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\\n * @param account The account whose pool is used to determine the market's risk parameters\\n * @param vToken The address of the vToken market\\n * @return The liquidation Incentive for the vToken, scaled by 1e18\\n */\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256) {\\n (, , uint256 li) = getLiquidationParams(userPoolId[account], vToken);\\n return li;\\n }\\n\\n /**\\n * @notice Returns the full list of vTokens for a given pool ID.\\n * @param poolId The ID of the pool whose vTokens are being queried.\\n * @return An array of vToken addresses associated with the pool.\\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\\n */\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory) {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n return pools[poolId].vTokens;\\n }\\n\\n /**\\n * @notice Returns the market configuration for a vToken in the core pool (poolId = 0).\\n * @dev Fetches the Market struct associated with the core pool and returns all relevant parameters.\\n * @param vToken The address of the vToken whose market configuration is to be fetched.\\n * @return isListed Whether the market is listed and enabled.\\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\\n * @return isVenus Whether this market is eligible for VENUS rewards.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The max liquidation incentive allowed for this market, in mantissa.\\n * @return marketPoolId The pool ID this market belongs to.\\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\\n */\\n function markets(\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n )\\n {\\n return poolMarkets(corePoolId, vToken);\\n }\\n\\n /**\\n * @notice Returns the market configuration for a vToken from _poolMarkets.\\n * @dev Fetches the Market struct associated with the poolId and returns all relevant parameters.\\n * @param poolId The ID of the pool whose market configuration is being queried.\\n * @param vToken The address of the vToken whose market configuration is to be fetched.\\n * @return isListed Whether the market is listed and enabled.\\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\\n * @return isVenus Whether this market is eligible for XVS rewards.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\\n * @return marketPoolId The pool ID this market belongs to.\\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\\n */\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n public\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n )\\n {\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n PoolMarketId key = getPoolMarketIndex(poolId, vToken);\\n Market storage m = _poolMarkets[key];\\n\\n return (\\n m.isListed,\\n m.collateralFactorMantissa,\\n m.isVenus,\\n m.liquidationThresholdMantissa,\\n m.liquidationIncentiveMantissa,\\n m.poolId,\\n m.isBorrowAllowed\\n );\\n }\\n\\n /**\\n * @notice Returns true if the user can switch to the given target pool, i.e.,\\n * all markets they have borrowed from are also borrowable in the target pool.\\n * @param account The address of the user attempting to switch pools.\\n * @param targetPoolId The pool ID the user wants to switch into.\\n * @return bool True if the switch is allowed, otherwise False.\\n */\\n function hasValidPoolBorrows(address account, uint96 targetPoolId) public view returns (bool) {\\n VToken[] memory assets = accountAssets[account];\\n if (targetPoolId != corePoolId && mintedVAIs[account] > 0) {\\n return false;\\n }\\n\\n for (uint256 i; i < assets.length; i++) {\\n VToken vToken = assets[i];\\n PoolMarketId index = getPoolMarketIndex(targetPoolId, address(vToken));\\n\\n if (!_poolMarkets[index].isBorrowAllowed) {\\n if (vToken.borrowBalanceStored(account) > 0) {\\n return false;\\n }\\n }\\n }\\n return true;\\n }\\n\\n function _updateDelegate(address approver, address delegate, bool approved) internal {\\n approvedDelegates[approver][delegate] = approved;\\n emit DelegateUpdated(approver, delegate, approved);\\n }\\n\\n function _addMarketInternal(VToken vToken) internal {\\n uint256 allMarketsLength = allMarkets.length;\\n for (uint256 i; i < allMarketsLength; ++i) {\\n require(allMarkets[i] != vToken, \\\"already added\\\");\\n }\\n allMarkets.push(vToken);\\n }\\n\\n function _initializeMarket(address vToken) internal {\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n\\n /*\\n * Update market state indices\\n */\\n if (supplyState.index == 0) {\\n // Initialize supply state index with default value\\n supplyState.index = venusInitialIndex;\\n }\\n\\n if (borrowState.index == 0) {\\n // Initialize borrow state index with default value\\n borrowState.index = venusInitialIndex;\\n }\\n\\n /*\\n * Update market state block numbers\\n */\\n supplyState.block = borrowState.block = blockNumber;\\n }\\n\\n function __supportMarket(VToken vToken) internal returns (uint256) {\\n ensureAllowed(\\\"_supportMarket(address)\\\");\\n\\n if (getCorePoolMarket(address(vToken)).isListed) {\\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\\n }\\n\\n vToken.isVToken(); // Sanity check to make sure its really a VToken\\n\\n // Note that isVenus is not in active use anymore\\n Market storage newMarket = getCorePoolMarket(address(vToken));\\n newMarket.isListed = true;\\n newMarket.isVenus = false;\\n newMarket.collateralFactorMantissa = 0;\\n\\n _addMarketInternal(vToken);\\n _initializeMarket(address(vToken));\\n\\n emit MarketListed(vToken);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n function _addPoolMarket(uint96 poolId, address vToken) internal {\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (!pools[poolId].isActive) revert InactivePool(poolId);\\n\\n // Core Pool Index\\n PoolMarketId index = getPoolMarketIndex(corePoolId, vToken);\\n if (!_poolMarkets[index].isListed) revert MarketNotListedInCorePool();\\n\\n // Pool Index\\n index = getPoolMarketIndex(poolId, vToken);\\n if (_poolMarkets[index].isListed) revert MarketAlreadyListed(poolId, vToken);\\n\\n Market storage m = _poolMarkets[index];\\n m.poolId = poolId;\\n m.isListed = true;\\n\\n pools[poolId].vTokens.push(vToken);\\n\\n emit PoolMarketInitialized(poolId, vToken);\\n }\\n\\n /**\\n * @notice Returns only the core risk parameters (CF, LI, LT) for a vToken in a specific pool.\\n * @dev If the pool is inactive, or if the vToken is not configured in the given pool and\\n * `allowCorePoolFallback` is enabled, falls back to the core pool (poolId = 0) values.\\n * @return collateralFactorMantissa The max borrowable percentage of collateral, in mantissa.\\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\\n */\\n function getLiquidationParams(\\n uint96 poolId,\\n address vToken\\n )\\n internal\\n view\\n returns (\\n uint256 collateralFactorMantissa,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa\\n )\\n {\\n PoolData storage pool = pools[poolId];\\n Market storage market;\\n\\n if (poolId == corePoolId || !pool.isActive) {\\n market = getCorePoolMarket(vToken);\\n } else {\\n PoolMarketId poolKey = getPoolMarketIndex(poolId, vToken);\\n Market storage poolMarket = _poolMarkets[poolKey];\\n market = (!poolMarket.isListed && pool.allowCorePoolFallback) ? getCorePoolMarket(vToken) : poolMarket;\\n }\\n\\n return (\\n market.collateralFactorMantissa,\\n market.liquidationThresholdMantissa,\\n market.liquidationIncentiveMantissa\\n );\\n }\\n}\\n\",\"keccak256\":\"0xaf0b4e25119fcc08d66e241032cea7ea6284771bfa5588e57dc9a50bbe689a32\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IMarketFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./IFacetBase.sol\\\";\\n\\ninterface IMarketFacet {\\n function isComptroller() external pure returns (bool);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint256 actualRepayAmount\\n ) external view returns (uint256, uint256);\\n\\n function checkMembership(address account, VToken vToken) external view returns (bool);\\n\\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256);\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\\n\\n function exitMarket(address vToken) external returns (uint256);\\n\\n function _supportMarket(VToken vToken) external returns (uint256);\\n\\n function supportMarket(VToken vToken) external returns (uint256);\\n\\n function isMarketListed(VToken vToken) external view returns (bool);\\n\\n function getAssetsIn(address account) external view returns (VToken[] memory);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function updateDelegate(address delegate, bool allowBorrows) external;\\n\\n function unlistMarket(address market) external returns (uint256);\\n\\n function createPool(string memory label) external returns (uint96);\\n\\n function enterPool(uint96 poolId) external;\\n\\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external;\\n\\n function removePoolMarket(uint96 poolId, address vToken) external;\\n\\n function markets(\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function hasValidPoolBorrows(address user, uint96 targetPoolId) external view returns (bool);\\n\\n function getCollateralFactor(address vToken) external view returns (uint256);\\n\\n function getLiquidationThreshold(address vToken) external view returns (uint256);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n}\\n\",\"keccak256\":\"0x11118e9ea5b6c8df34d55ae85f4310ef9f6a7590b3a2202fbc7a2bb0b8572699\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b5061395e8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610458575f3560e01c80639bb27d6211610242578063d0d1303611610140578063e0f6123d116100bf578063f02fdf9711610084578063f02fdf9714610b6b578063f445d70314610b7e578063f851a44014610bab578063f968273214610bbd578063fa6331d814610bd0575f80fd5b8063e0f6123d14610ae3578063e37d4b7914610b05578063e85a296014610b3c578063e875544614610b4f578063ede4edd014610b58575f80fd5b8063d686e9ee11610105578063d686e9ee14610a7f578063d7c46d2d14610a92578063dce1544914610aaa578063dcfbc0c714610abd578063ddbf54fd14610ad0575f80fd5b8063d0d1303614610a2c578063d137f36e14610a3f578063d3270f9914610a52578063d463654c14610a65578063d585c3c614610a6c575f80fd5b8063bb82aa5e116101cc578063c488847b11610191578063c488847b146109c5578063c5b4db55146109d8578063c5f956af14610a06578063c7ee005e14610a19578063cab4f84c14610897575f80fd5b8063bb82aa5e14610959578063bbb8864a1461096c578063bec04f721461098b578063bf32442d14610994578063c2998238146109a5575f80fd5b8063abfceffc11610212578063abfceffc146108bd578063afd3783b146108d0578063b0772d0b146108e3578063b2eafc39146108eb578063b8324c7c146108fe575f80fd5b80639bb27d6214610871578063a657e57914610884578063a76b3fda14610897578063a78dc775146108aa575f80fd5b80634a5844321161035a5780637dc0d1d0116102d95780638e8f294b1161029e5780638e8f294b1461080d5780639254f5e514610820578063929fe9a11461083357806394b2294b1461084657806396c990641461084f575f80fd5b80637dc0d1d0146107975780637fb8e8cd146107aa57806389c13be0146107b75780638a7dc165146107cc5780638c1ac18a146107eb575f80fd5b8063719f701b1161031f578063719f701b14610716578063737690991461071f578063765513831461075f5780637b86e42c146107715780637d172bd514610784575f80fd5b80634a584432146106925780634d99c776146106b157806352d84d1e146106c45780635dd3fc9d146106d757806363e0d634146106f6575f80fd5b806321af4569116103e65780633093c11e116103ab5780633093c11e146105db5780633d98a1e5146106355780634088c73e1461064857806341a18d2c14610655578063425fad581461067f575f80fd5b806321af456914610558578063236175851461058357806324a3d6221461059657806326782247146105a95780632bc7e29e146105bc575f80fd5b806308e0225c1161042c57806308e0225c146104bd5780630db4b4e5146104e75780630ef332ca146104f057806310b983381461051857806319ef3e8b14610545575f80fd5b80627e3dd21461045c57806302c3bcbb1461047457806304ef9d58146104a15780630686dab6146104aa575b5f80fd5b60015b60405190151581526020015b60405180910390f35b6104936104823660046130f7565b60276020525f908152604090205481565b60405190815260200161046b565b61049360225481565b6104936104b83660046130f7565b610bd9565b6104936104cb366004613112565b601360209081525f928352604080842090915290825290205481565b610493601d5481565b6105036104fe366004613149565b61109f565b6040805192835260208301919091520161046b565b61045f610526366004613112565b602c60209081525f928352604080842090915290825290205460ff1681565b610493610553366004613197565b61113c565b601e5461056b906001600160a01b031681565b6040516001600160a01b03909116815260200161046b565b6104936105913660046130f7565b6111ce565b600a5461056b906001600160a01b031681565b60015461056b906001600160a01b031681565b6104936105ca3660046130f7565b60166020525f908152604090205481565b6105ee6105e93660046131fd565b6111e4565b604080519715158852602088019690965293151594860194909452606085019190915260808401526001600160601b0390911660a0830152151560c082015260e00161046b565b61045f6106433660046130f7565b6112a9565b60185461045f9060ff1681565b610493610663366004613112565b601260209081525f928352604080842090915290825290205481565b60185461045f9062010000900460ff1681565b6104936106a03660046130f7565b601f6020525f908152604090205481565b6104936106bf3660046131fd565b6112bd565b61056b6106d2366004613217565b6112de565b6104936106e53660046130f7565b602b6020525f908152604090205481565b61070961070436600461322e565b611306565b60405161046b9190613247565b610493601c5481565b61074761072d3660046130f7565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161046b565b60185461045f90610100900460ff1681565b61049361077f3660046130f7565b6113df565b601b5461056b906001600160a01b031681565b60045461056b906001600160a01b031681565b60395461045f9060ff1681565b6107ca6107c53660046132d4565b6113f4565b005b6104936107da3660046130f7565b60146020525f908152604090205481565b61045f6107f93660046130f7565b602d6020525f908152604090205460ff1681565b6105ee61081b3660046130f7565b6114b1565b60155461056b906001600160a01b031681565b61045f610841366004613112565b6114d9565b61049360075481565b61086261085d36600461322e565b611508565b60405161046b93929190613369565b60255461056b906001600160a01b031681565b603754610747906001600160601b031681565b6104936108a53660046130f7565b6115b5565b6105036108b8366004613392565b6115bf565b6107096108cb3660046130f7565b61164c565b6104936108de366004613112565b6117a9565b6107096117e0565b60205461056b906001600160a01b031681565b61093561090c3660046130f7565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161046b565b60025461056b906001600160a01b031681565b61049361097a3660046130f7565b602a6020525f908152604090205481565b61049360175481565b6033546001600160a01b031661056b565b6109b86109b33660046133bc565b611840565b60405161046b91906133fb565b6105036109d3366004613432565b6118f9565b6109ee6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b03909116815260200161046b565b60215461056b906001600160a01b031681565b60315461056b906001600160a01b031681565b610747610a3a366004613484565b61198d565b6107ca610a4d3660046131fd565b611a93565b60265461056b906001600160a01b031681565b6107475f81565b610493610a7a366004613112565b611ced565b610493610a8d3660046130f7565b611d63565b60395461056b9061010090046001600160a01b031681565b61056b610ab8366004613392565b611d78565b60035461056b906001600160a01b031681565b6107ca610ade36600461353c565b611dac565b61045f610af13660046130f7565b60386020525f908152604090205460ff1681565b610935610b133660046130f7565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61045f610b4a366004613568565b611e3e565b61049360055481565b610493610b663660046130f7565b611e82565b61045f610b79366004613597565b61212b565b61045f610b8c366004613112565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461056b906001600160a01b031681565b6107ca610bcb36600461322e565b6122ba565b610493601a5481565b5f610c1060405180604001604052806015815260200174756e6c6973744d61726b657428616464726573732960581b8152506124a8565b5f610c1a83612558565b805490915060ff16610c3957610c326009601861257a565b9392505050565b610c44836002611e3e565b610c955760405162461bcd60e51b815260206004820152601b60248201527f626f72726f7720616374696f6e206973206e6f7420706175736564000000000060448201526064015b60405180910390fd5b610c9f835f611e3e565b610ceb5760405162461bcd60e51b815260206004820152601960248201527f6d696e7420616374696f6e206973206e6f7420706175736564000000000000006044820152606401610c8c565b610cf6836001611e3e565b610d425760405162461bcd60e51b815260206004820152601b60248201527f72656465656d20616374696f6e206973206e6f742070617573656400000000006044820152606401610c8c565b610d4d836003611e3e565b610d995760405162461bcd60e51b815260206004820152601a60248201527f726570617920616374696f6e206973206e6f74207061757365640000000000006044820152606401610c8c565b610da4836007611e3e565b610dfa5760405162461bcd60e51b815260206004820152602160248201527f656e746572206d61726b657420616374696f6e206973206e6f742070617573656044820152601960fa1b6064820152608401610c8c565b610e05836005611e3e565b610e515760405162461bcd60e51b815260206004820152601e60248201527f6c697175696461746520616374696f6e206973206e6f742070617573656400006044820152606401610c8c565b610e5c836004611e3e565b610ea85760405162461bcd60e51b815260206004820152601a60248201527f7365697a6520616374696f6e206973206e6f74207061757365640000000000006044820152606401610c8c565b610eb3836006611e3e565b610eff5760405162461bcd60e51b815260206004820152601d60248201527f7472616e7366657220616374696f6e206973206e6f74207061757365640000006044820152606401610c8c565b610f0a836008611e3e565b610f565760405162461bcd60e51b815260206004820181905260248201527f65786974206d61726b657420616374696f6e206973206e6f74207061757365646044820152606401610c8c565b6001600160a01b0383165f908152601f602052604090205415610fb15760405162461bcd60e51b81526020600482015260136024820152720626f72726f7720636170206973206e6f74203606c1b6044820152606401610c8c565b6001600160a01b0383165f908152602760205260409020541561100c5760405162461bcd60e51b81526020600482015260136024820152720737570706c7920636170206973206e6f74203606c1b6044820152606401610c8c565b60018101541561105e5760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206973206e6f7420300000000000006044820152606401610c8c565b805460ff191681556040516001600160a01b038416907f302feb03efd5741df80efe7f97f5d93d74d46a542a3d312d0faae64fa1f3e0e9905f90a25f610c32565b602654604051630a5d5a0560e41b81526001600160a01b03868116600483015230602483015285811660448301528481166064830152608482018490525f92839283928392169063a5d5a0509060a4016040805180830381865afa158015611109573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112d91906135de565b90999098509650505050505050565b6001600160a01b0383165f908152603560205260408120548190819061116b906001600160601b0316866125f1565b5090925090505f846001811115611184576111846135ca565b0361119157509050610c32565b60018460018111156111a5576111a56135ca565b036111b3579150610c329050565b83604051632f03799f60e11b8152600401610c8c9190613620565b5f806111da5f846125f1565b5090949350505050565b5f805f805f805f60375f9054906101000a90046001600160601b03166001600160601b0316896001600160601b0316111561123d57604051632db8671b60e11b81526001600160601b038a166004820152602401610c8c565b5f6112488a8a6112bd565b5f9081526009602052604090208054600182015460038301546004840154600585015460069095015460ff9485169d50929b50908316995097509195506001600160601b0382169450600160601b9091041691505092959891949750929550565b5f6112b382612558565b5460ff1692915050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d81815481106112ed575f80fd5b5f918252602090912001546001600160a01b0316905081565b6037546060906001600160601b03908116908316111561134457604051632db8671b60e11b81526001600160601b0383166004820152602401610c8c565b6001600160601b03821661136b57604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f90815260366020908152604091829020600101805483518184028101840190945280845290918301828280156113d357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116113b5575b50505050509050919050565b5f806113eb5f846125f1565b50949350505050565b611415604051806060016040528060228152602001613907602291396124a8565b828015806114235750808214155b156114415760405163512509d360e11b815260040160405180910390fd5b5f5b818110156114a9576114a18686838181106114605761146061362e565b9050602002016020810190611475919061322e565b8585848181106114875761148761362e565b905060200201602081019061149c91906130f7565b6126a3565b600101611443565b505050505050565b5f805f805f805f6114c25f896111e4565b959e949d50929b5090995097509550909350915050565b5f6114e382612558565b6001600160a01b03939093165f90815260029093016020525050604090205460ff1690565b60366020525f908152604090208054819061152290613642565b80601f016020809104026020016040519081016040528092919081815260200182805461154e90613642565b80156115995780601f1061157057610100808354040283529160200191611599565b820191905f5260205f20905b81548152906001019060200180831161157c57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6112d882612886565b6026546040516304f65f8b60e21b81523060048201526001600160a01b038481166024830152604482018490525f9283928392839216906313d97e2c906064016040805180830381865afa158015611619573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061163d91906135de565b909450925050505b9250929050565b6001600160a01b0381165f90815260086020908152604080832080548251818502810185019093528083526060949384939291908301828280156116b757602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611699575b505050505090505f815190505f8167ffffffffffffffff8111156116dd576116dd613470565b604051908082528060200260200182016040528015611706578160200160208202803683370190505b5090505f5b8281101561179c575f6117368583815181106117295761172961362e565b6020026020010151612558565b805490915060ff1615611793578482815181106117555761175561362e565b602002602001015183878151811061176f5761176f61362e565b6001600160a01b03909216602092830291909101909101526117908661368e565b95505b5060010161170b565b5092835250909392505050565b6001600160a01b0382165f9081526035602052604081205481906117d6906001600160601b0316846125f1565b9695505050505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561183657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611818575b5050505050905090565b6060815f8167ffffffffffffffff81111561185d5761185d613470565b604051908082528060200260200182016040528015611886578160200160208202803683370190505b5090505f5b828110156113eb576118c38686838181106118a8576118a861362e565b90506020020160208101906118bd91906130f7565b336129ba565b60148111156118d4576118d46135ca565b8282815181106118e6576118e661362e565b602090810291909101015260010161188b565b602654604051630779996560e11b81523060048201526001600160a01b0385811660248301528481166044830152606482018490525f928392839283921690630ef332ca906084016040805180830381865afa15801561195b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197f91906135de565b909890975095505050505050565b5f6119c160405180604001604052806012815260200171637265617465506f6f6c28737472696e672960701b8152506124a8565b81515f036119e25760405163522e397360e11b815260040160405180910390fd5b603780545f919082906119fd906001600160601b03166136a6565b82546001600160601b038083166101009490940a848102910219909116179092555f90815260366020526040902090915080611a39858261370f565b5060028101805460ff191660011790556040516001600160601b038316907fc419386a8582a5374f4db03fdbb9fd99c73ef32d6ce9fc3a8c249e97bf31f9af90611a849087906137cb565b60405180910390a25092915050565b611ad16040518060400160405280602081526020017f72656d6f7665506f6f6c4d61726b65742875696e7439362c61646472657373298152506124a8565b6001600160601b038216611af857604051630203217b60e61b815260040160405180910390fd5b5f611b0383836112bd565b5f8181526009602052604090205490915060ff16611b4e576040516338ddb96b60e11b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c8c565b6001600160601b0383165f908152603660205260408120600101805490915b81811015611c5b57846001600160a01b0316838281548110611b9157611b9161362e565b5f918252602090912001546001600160a01b031603611c535782611bb66001846137dd565b81548110611bc657611bc661362e565b905f5260205f20015f9054906101000a90046001600160a01b0316838281548110611bf357611bf361362e565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480611c2e57611c2e6137f0565b5f8281526020902081015f1990810180546001600160a01b0319169055019055611c5b565b600101611b6d565b505f83815260096020526040808220805460ff199081168255600182018490556003820180549091169055600481018390556005810183905560060180546cffffffffffffffffffffffffff19169055516001600160a01b038616916001600160601b038816917fc8bef274db6d8c804aba68a69e64268bcfe7dd0aead2efcec0cac73a2df56e129190a35050505050565b5f336001600160a01b03841614801590611d2a57506001600160a01b0383165f908152602c6020908152604080832033845290915290205460ff16155b15611d48576040516337248ad960e01b815260040160405180910390fd5b611d5282846129ba565b6014811115610c3257610c326135ca565b5f80611d6f5f846125f1565b95945050505050565b6008602052815f5260405f208181548110611d91575f80fd5b5f918252602090912001546001600160a01b03169150829050565b611db582612a8d565b335f908152602c602090815260408083206001600160a01b038616845290915290205481151560ff909116151503611e2f5760405162461bcd60e51b815260206004820152601b60248201527f44656c65676174696f6e2073746174757320756e6368616e67656400000000006044820152606401610c8c565b611e3a338383612adb565b5050565b6001600160a01b0382165f90815260296020526040812081836008811115611e6857611e686135ca565b815260208101919091526040015f205460ff169392505050565b5f611e8e826008612b47565b6040516361bfb47160e11b815233600482015282905f90819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa158015611ed8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611efc9190613804565b50925092509250825f14611f525760405162461bcd60e51b815260206004820152601960248201527f6765744163636f756e74536e617073686f74206661696c6564000000000000006044820152606401610c8c565b8015611f64576117d6600c600261257a565b5f611f70873385612b91565b90508015611f9057611f85600e600383612c38565b979650505050505050565b5f611f9a86612558565b335f90815260028201602052604090205490915060ff16611fc2575f98975050505050505050565b335f9081526002820160209081526040808320805460ff1916905560089091528120805490915b818110156120d757886001600160a01b031683828154811061200d5761200d61362e565b5f918252602090912001546001600160a01b0316036120cf57826120326001846137dd565b815481106120425761204261362e565b905f5260205f20015f9054906101000a90046001600160a01b031683828154811061206f5761206f61362e565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550828054806120aa576120aa6137f0565b5f8281526020902081015f1990810180546001600160a01b03191690550190556120d7565b600101611fe9565b8181106120e6576120e6613837565b60405133906001600160a01b038b16907fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d905f90a35f9b9a5050505050505050505050565b6001600160a01b0382165f9081526008602090815260408083208054825181850281018501909352808352849383018282801561218f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612171575b50939450505050506001600160601b038316158015906121c557506001600160a01b0384165f9081526016602052604090205415155b156121d3575f9150506112d8565b5f5b81518110156122af575f8282815181106121f1576121f161362e565b602002602001015190505f61220686836112bd565b5f81815260096020526040902060060154909150600160601b900460ff166122a5576040516395dd919360e01b81526001600160a01b0388811660048301525f91908416906395dd919390602401602060405180830381865afa15801561226f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612293919061384b565b11156122a5575f9450505050506112d8565b50506001016121d5565b506001949350505050565b6037546001600160601b0390811690821611156122f557604051632db8671b60e11b81526001600160601b0382166004820152602401610c8c565b335f908152603560205260409020546001600160601b039081169082160361233057604051631c9d4f3960e31b815260040160405180910390fd5b6001600160601b0381161580159061236357506001600160601b0381165f9081526036602052604090206002015460ff16155b1561238c57604051632da4cc0560e01b81526001600160601b0382166004820152602401610c8c565b612396338261212b565b6123b35760405163592ec11d60e01b815260040160405180910390fd5b335f818152603560209081526040918290205491516001600160601b03928316815291841692917f9181876220501cdac3aa7278fd34e9bd150c30a27b6ed95458fe859761b071f7910160405180910390a3335f81815260356020526040812080546bffffffffffffffffffffffff19166001600160601b0385161790559081906124419082808080612cb7565b9193509091505f905082601481111561245c5761245c6135ca565b14158061246857505f81115b156124a35781601481111561247f5761247f6135ca565b60405163c978466160e01b8152600481019190915260248101829052604401610c8c565b505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906124da9033908590600401613862565b602060405180830381865afa1580156124f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125199190613885565b6125555760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610c8c565b50565b5f60095f6125665f856112bd565b81526020019081526020015f209050919050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360148111156125ae576125ae6135ca565b83601a8111156125c0576125c06135ca565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610c3257610c326135ca565b6001600160601b0382165f818152603660205260408120909182918291829015806126215750600282015460ff16155b156126365761262f86612558565b9050612685565b5f61264188886112bd565b5f81815260096020526040902080549192509060ff1615801561266d57506002840154610100900460ff165b6126775780612680565b61268088612558565b925050505b80600101548160040154826005015494509450945050509250925092565b6001600160601b0382166126ca57604051630203217b60e61b815260040160405180910390fd5b6037546001600160601b03908116908316111561270557604051632db8671b60e11b81526001600160601b0383166004820152602401610c8c565b6001600160601b0382165f9081526036602052604090206002015460ff1661274b57604051632da4cc0560e01b81526001600160601b0383166004820152602401610c8c565b5f6127565f836112bd565b5f8181526009602052604090205490915060ff16612787576040516386dccab760e01b815260040160405180910390fd5b61279183836112bd565b5f8181526009602052604090205490915060ff16156127dd5760405163d9d72f2b60e01b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c8c565b5f8181526009602090815260408083206006810180546bffffffffffffffffffffffff19166001600160601b038916908117909155815460ff19166001908117835581865260368552838620810180549182018155865293852090930180546001600160a01b0319166001600160a01b038816908117909155915190939192917f2159e9508e372ac69e1047a124c5478445206066e5d7df7e4214a1986cd78c8091a350505050565b5f6128c56040518060400160405280601781526020017f5f737570706f72744d61726b65742861646472657373290000000000000000008152506124a8565b6128ce82612558565b5460ff16156128e3576112d8600a601161257a565b816001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561291f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129439190613885565b505f61294e83612558565b8054600160ff19918216811783556003830180549092169091555f90820155905061297883612d80565b61298183612e56565b6040516001600160a01b038416907fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f905f90a25f610c32565b5f6129c6836007612b47565b5f6129d084612558565b90506129db81612f18565b6001600160a01b0383165f90815260028201602052604090205460ff1615612a06575f9150506112d8565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b6001600160a01b0381166125555760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610c8c565b6001600160a01b038381165f818152602c6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fcb325b7784f78486e42849c7a50b8c5ee008d00cd90e108a58912c0fcb6288b4910160405180910390a3505050565b612b518282611e3e565b15611e3a5760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610c8c565b5f612ba3612b9e85612558565b612f18565b612bac84612558565b6001600160a01b0384165f908152600291909101602052604090205460ff16612bd657505f610c32565b5f80612be58587865f80612cb7565b9193509091505f9050826014811115612c0057612c006135ca565b14612c2057816014811115612c1757612c176135ca565b92505050610c32565b8015612c2d576004612c17565b5f9695505050505050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846014811115612c6c57612c6c6135ca565b84601a811115612c7e57612c7e6135ca565b604080519283526020830191909152810184905260600160405180910390a1836014811115612caf57612caf6135ca565b949350505050565b5f808080846001811115612ccd57612ccd6135ca565b03612cdb57612cdb88612f5d565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e90612d199030908f908f908f908f908f906004016138a0565b606060405180830381865afa158015612d34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d5891906138db565b925092509250826014811115612d7057612d706135ca565b9b919a5098509650505050505050565b600d545f5b81811015612e0357826001600160a01b0316600d8281548110612daa57612daa61362e565b5f918252602090912001546001600160a01b031603612dfb5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481859191959609a1b6044820152606401610c8c565b600101612d85565b5050600d80546001810182555f919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b5f612e5f61307b565b6001600160a01b0383165f908152601060209081526040808320601190925282208154939450909290916001600160e01b039091169003612eba5781546001600160e01b0319166ec097ce7bc90715b34b9f10000000001782555b80546001600160e01b03165f03612eeb5780546001600160e01b0319166ec097ce7bc90715b34b9f10000000001781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b805460ff166125555760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610c8c565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015612fd357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612fb5575b505083519394505f925050505b8181101561307457836001600160a01b031663a9c3cab18483815181106130095761300961362e565b60200260200101516040518263ffffffff1660e01b815260040161303c91906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015613053575f80fd5b505af1158015613065573d5f803e3d5ffd5b50505050806001019050612fe0565b5050505050565b5f6130af4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b8152506130b4565b905090565b5f8164010000000084106130db5760405162461bcd60e51b8152600401610c8c91906137cb565b509192915050565b6001600160a01b0381168114612555575f80fd5b5f60208284031215613107575f80fd5b8135610c32816130e3565b5f8060408385031215613123575f80fd5b823561312e816130e3565b9150602083013561313e816130e3565b809150509250929050565b5f805f806080858703121561315c575f80fd5b8435613167816130e3565b93506020850135613177816130e3565b92506040850135613187816130e3565b9396929550929360600135925050565b5f805f606084860312156131a9575f80fd5b83356131b4816130e3565b925060208401356131c4816130e3565b91506040840135600281106131d7575f80fd5b809150509250925092565b80356001600160601b03811681146131f8575f80fd5b919050565b5f806040838503121561320e575f80fd5b61312e836131e2565b5f60208284031215613227575f80fd5b5035919050565b5f6020828403121561323e575f80fd5b610c32826131e2565b602080825282518282018190525f9190848201906040850190845b818110156132875783516001600160a01b031683529284019291840191600101613262565b50909695505050505050565b5f8083601f8401126132a3575f80fd5b50813567ffffffffffffffff8111156132ba575f80fd5b6020830191508360208260051b8501011115611645575f80fd5b5f805f80604085870312156132e7575f80fd5b843567ffffffffffffffff808211156132fe575f80fd5b61330a88838901613293565b90965094506020870135915080821115613322575f80fd5b5061332f87828801613293565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61337b606083018661333b565b931515602083015250901515604090910152919050565b5f80604083850312156133a3575f80fd5b82356133ae816130e3565b946020939093013593505050565b5f80602083850312156133cd575f80fd5b823567ffffffffffffffff8111156133e3575f80fd5b6133ef85828601613293565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b8181101561328757835183529284019291840191600101613416565b5f805f60608486031215613444575f80fd5b833561344f816130e3565b9250602084013561345f816130e3565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215613494575f80fd5b813567ffffffffffffffff808211156134ab575f80fd5b818401915084601f8301126134be575f80fd5b8135818111156134d0576134d0613470565b604051601f8201601f19908116603f011681019083821181831017156134f8576134f8613470565b81604052828152876020848701011115613510575f80fd5b826020860160208301375f928101602001929092525095945050505050565b8015158114612555575f80fd5b5f806040838503121561354d575f80fd5b8235613558816130e3565b9150602083013561313e8161352f565b5f8060408385031215613579575f80fd5b8235613584816130e3565b915060208301356009811061313e575f80fd5b5f80604083850312156135a8575f80fd5b82356135b3816130e3565b91506135c1602084016131e2565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156135ef575f80fd5b505080516020909101519092909150565b6002811061361c57634e487b7160e01b5f52602160045260245ffd5b9052565b602081016112d88284613600565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061365657607f821691505b60208210810361367457634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161369f5761369f61367a565b5060010190565b5f6001600160601b038083168181036136c1576136c161367a565b6001019392505050565b601f8211156124a357805f5260205f20601f840160051c810160208510156136f05750805b601f840160051c820191505b81811015613074575f81556001016136fc565b815167ffffffffffffffff81111561372957613729613470565b61373d816137378454613642565b846136cb565b602080601f831160018114613770575f84156137595750858301515b5f19600386901b1c1916600185901b1785556114a9565b5f85815260208120601f198616915b8281101561379e5788860151825594840194600190910190840161377f565b50858210156137bb57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b602081525f610c32602083018461333b565b818103818111156112d8576112d861367a565b634e487b7160e01b5f52603160045260245ffd5b5f805f8060808587031215613817575f80fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b5f52600160045260245ffd5b5f6020828403121561385b575f80fd5b5051919050565b6001600160a01b03831681526040602082018190525f90612caf9083018461333b565b5f60208284031215613895575f80fd5b8151610c328161352f565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101611f8560a0830184613600565b5f805f606084860312156138ed575f80fd5b835192506020840151915060408401519050925092509256fe616464506f6f6c4d61726b6574732875696e7439365b5d2c616464726573735b5d29a264697066735822122058abb9325ca9755ea139c408f1749ca1e81f0e897c695239d1deb995050db88a64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610458575f3560e01c80639bb27d6211610242578063d0d1303611610140578063e0f6123d116100bf578063f02fdf9711610084578063f02fdf9714610b6b578063f445d70314610b7e578063f851a44014610bab578063f968273214610bbd578063fa6331d814610bd0575f80fd5b8063e0f6123d14610ae3578063e37d4b7914610b05578063e85a296014610b3c578063e875544614610b4f578063ede4edd014610b58575f80fd5b8063d686e9ee11610105578063d686e9ee14610a7f578063d7c46d2d14610a92578063dce1544914610aaa578063dcfbc0c714610abd578063ddbf54fd14610ad0575f80fd5b8063d0d1303614610a2c578063d137f36e14610a3f578063d3270f9914610a52578063d463654c14610a65578063d585c3c614610a6c575f80fd5b8063bb82aa5e116101cc578063c488847b11610191578063c488847b146109c5578063c5b4db55146109d8578063c5f956af14610a06578063c7ee005e14610a19578063cab4f84c14610897575f80fd5b8063bb82aa5e14610959578063bbb8864a1461096c578063bec04f721461098b578063bf32442d14610994578063c2998238146109a5575f80fd5b8063abfceffc11610212578063abfceffc146108bd578063afd3783b146108d0578063b0772d0b146108e3578063b2eafc39146108eb578063b8324c7c146108fe575f80fd5b80639bb27d6214610871578063a657e57914610884578063a76b3fda14610897578063a78dc775146108aa575f80fd5b80634a5844321161035a5780637dc0d1d0116102d95780638e8f294b1161029e5780638e8f294b1461080d5780639254f5e514610820578063929fe9a11461083357806394b2294b1461084657806396c990641461084f575f80fd5b80637dc0d1d0146107975780637fb8e8cd146107aa57806389c13be0146107b75780638a7dc165146107cc5780638c1ac18a146107eb575f80fd5b8063719f701b1161031f578063719f701b14610716578063737690991461071f578063765513831461075f5780637b86e42c146107715780637d172bd514610784575f80fd5b80634a584432146106925780634d99c776146106b157806352d84d1e146106c45780635dd3fc9d146106d757806363e0d634146106f6575f80fd5b806321af4569116103e65780633093c11e116103ab5780633093c11e146105db5780633d98a1e5146106355780634088c73e1461064857806341a18d2c14610655578063425fad581461067f575f80fd5b806321af456914610558578063236175851461058357806324a3d6221461059657806326782247146105a95780632bc7e29e146105bc575f80fd5b806308e0225c1161042c57806308e0225c146104bd5780630db4b4e5146104e75780630ef332ca146104f057806310b983381461051857806319ef3e8b14610545575f80fd5b80627e3dd21461045c57806302c3bcbb1461047457806304ef9d58146104a15780630686dab6146104aa575b5f80fd5b60015b60405190151581526020015b60405180910390f35b6104936104823660046130f7565b60276020525f908152604090205481565b60405190815260200161046b565b61049360225481565b6104936104b83660046130f7565b610bd9565b6104936104cb366004613112565b601360209081525f928352604080842090915290825290205481565b610493601d5481565b6105036104fe366004613149565b61109f565b6040805192835260208301919091520161046b565b61045f610526366004613112565b602c60209081525f928352604080842090915290825290205460ff1681565b610493610553366004613197565b61113c565b601e5461056b906001600160a01b031681565b6040516001600160a01b03909116815260200161046b565b6104936105913660046130f7565b6111ce565b600a5461056b906001600160a01b031681565b60015461056b906001600160a01b031681565b6104936105ca3660046130f7565b60166020525f908152604090205481565b6105ee6105e93660046131fd565b6111e4565b604080519715158852602088019690965293151594860194909452606085019190915260808401526001600160601b0390911660a0830152151560c082015260e00161046b565b61045f6106433660046130f7565b6112a9565b60185461045f9060ff1681565b610493610663366004613112565b601260209081525f928352604080842090915290825290205481565b60185461045f9062010000900460ff1681565b6104936106a03660046130f7565b601f6020525f908152604090205481565b6104936106bf3660046131fd565b6112bd565b61056b6106d2366004613217565b6112de565b6104936106e53660046130f7565b602b6020525f908152604090205481565b61070961070436600461322e565b611306565b60405161046b9190613247565b610493601c5481565b61074761072d3660046130f7565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161046b565b60185461045f90610100900460ff1681565b61049361077f3660046130f7565b6113df565b601b5461056b906001600160a01b031681565b60045461056b906001600160a01b031681565b60395461045f9060ff1681565b6107ca6107c53660046132d4565b6113f4565b005b6104936107da3660046130f7565b60146020525f908152604090205481565b61045f6107f93660046130f7565b602d6020525f908152604090205460ff1681565b6105ee61081b3660046130f7565b6114b1565b60155461056b906001600160a01b031681565b61045f610841366004613112565b6114d9565b61049360075481565b61086261085d36600461322e565b611508565b60405161046b93929190613369565b60255461056b906001600160a01b031681565b603754610747906001600160601b031681565b6104936108a53660046130f7565b6115b5565b6105036108b8366004613392565b6115bf565b6107096108cb3660046130f7565b61164c565b6104936108de366004613112565b6117a9565b6107096117e0565b60205461056b906001600160a01b031681565b61093561090c3660046130f7565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161046b565b60025461056b906001600160a01b031681565b61049361097a3660046130f7565b602a6020525f908152604090205481565b61049360175481565b6033546001600160a01b031661056b565b6109b86109b33660046133bc565b611840565b60405161046b91906133fb565b6105036109d3366004613432565b6118f9565b6109ee6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b03909116815260200161046b565b60215461056b906001600160a01b031681565b60315461056b906001600160a01b031681565b610747610a3a366004613484565b61198d565b6107ca610a4d3660046131fd565b611a93565b60265461056b906001600160a01b031681565b6107475f81565b610493610a7a366004613112565b611ced565b610493610a8d3660046130f7565b611d63565b60395461056b9061010090046001600160a01b031681565b61056b610ab8366004613392565b611d78565b60035461056b906001600160a01b031681565b6107ca610ade36600461353c565b611dac565b61045f610af13660046130f7565b60386020525f908152604090205460ff1681565b610935610b133660046130f7565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61045f610b4a366004613568565b611e3e565b61049360055481565b610493610b663660046130f7565b611e82565b61045f610b79366004613597565b61212b565b61045f610b8c366004613112565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461056b906001600160a01b031681565b6107ca610bcb36600461322e565b6122ba565b610493601a5481565b5f610c1060405180604001604052806015815260200174756e6c6973744d61726b657428616464726573732960581b8152506124a8565b5f610c1a83612558565b805490915060ff16610c3957610c326009601861257a565b9392505050565b610c44836002611e3e565b610c955760405162461bcd60e51b815260206004820152601b60248201527f626f72726f7720616374696f6e206973206e6f7420706175736564000000000060448201526064015b60405180910390fd5b610c9f835f611e3e565b610ceb5760405162461bcd60e51b815260206004820152601960248201527f6d696e7420616374696f6e206973206e6f7420706175736564000000000000006044820152606401610c8c565b610cf6836001611e3e565b610d425760405162461bcd60e51b815260206004820152601b60248201527f72656465656d20616374696f6e206973206e6f742070617573656400000000006044820152606401610c8c565b610d4d836003611e3e565b610d995760405162461bcd60e51b815260206004820152601a60248201527f726570617920616374696f6e206973206e6f74207061757365640000000000006044820152606401610c8c565b610da4836007611e3e565b610dfa5760405162461bcd60e51b815260206004820152602160248201527f656e746572206d61726b657420616374696f6e206973206e6f742070617573656044820152601960fa1b6064820152608401610c8c565b610e05836005611e3e565b610e515760405162461bcd60e51b815260206004820152601e60248201527f6c697175696461746520616374696f6e206973206e6f742070617573656400006044820152606401610c8c565b610e5c836004611e3e565b610ea85760405162461bcd60e51b815260206004820152601a60248201527f7365697a6520616374696f6e206973206e6f74207061757365640000000000006044820152606401610c8c565b610eb3836006611e3e565b610eff5760405162461bcd60e51b815260206004820152601d60248201527f7472616e7366657220616374696f6e206973206e6f74207061757365640000006044820152606401610c8c565b610f0a836008611e3e565b610f565760405162461bcd60e51b815260206004820181905260248201527f65786974206d61726b657420616374696f6e206973206e6f74207061757365646044820152606401610c8c565b6001600160a01b0383165f908152601f602052604090205415610fb15760405162461bcd60e51b81526020600482015260136024820152720626f72726f7720636170206973206e6f74203606c1b6044820152606401610c8c565b6001600160a01b0383165f908152602760205260409020541561100c5760405162461bcd60e51b81526020600482015260136024820152720737570706c7920636170206973206e6f74203606c1b6044820152606401610c8c565b60018101541561105e5760405162461bcd60e51b815260206004820152601a60248201527f636f6c6c61746572616c20666163746f72206973206e6f7420300000000000006044820152606401610c8c565b805460ff191681556040516001600160a01b038416907f302feb03efd5741df80efe7f97f5d93d74d46a542a3d312d0faae64fa1f3e0e9905f90a25f610c32565b602654604051630a5d5a0560e41b81526001600160a01b03868116600483015230602483015285811660448301528481166064830152608482018490525f92839283928392169063a5d5a0509060a4016040805180830381865afa158015611109573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112d91906135de565b90999098509650505050505050565b6001600160a01b0383165f908152603560205260408120548190819061116b906001600160601b0316866125f1565b5090925090505f846001811115611184576111846135ca565b0361119157509050610c32565b60018460018111156111a5576111a56135ca565b036111b3579150610c329050565b83604051632f03799f60e11b8152600401610c8c9190613620565b5f806111da5f846125f1565b5090949350505050565b5f805f805f805f60375f9054906101000a90046001600160601b03166001600160601b0316896001600160601b0316111561123d57604051632db8671b60e11b81526001600160601b038a166004820152602401610c8c565b5f6112488a8a6112bd565b5f9081526009602052604090208054600182015460038301546004840154600585015460069095015460ff9485169d50929b50908316995097509195506001600160601b0382169450600160601b9091041691505092959891949750929550565b5f6112b382612558565b5460ff1692915050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d81815481106112ed575f80fd5b5f918252602090912001546001600160a01b0316905081565b6037546060906001600160601b03908116908316111561134457604051632db8671b60e11b81526001600160601b0383166004820152602401610c8c565b6001600160601b03821661136b57604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f90815260366020908152604091829020600101805483518184028101840190945280845290918301828280156113d357602002820191905f5260205f20905b81546001600160a01b031681526001909101906020018083116113b5575b50505050509050919050565b5f806113eb5f846125f1565b50949350505050565b611415604051806060016040528060228152602001613907602291396124a8565b828015806114235750808214155b156114415760405163512509d360e11b815260040160405180910390fd5b5f5b818110156114a9576114a18686838181106114605761146061362e565b9050602002016020810190611475919061322e565b8585848181106114875761148761362e565b905060200201602081019061149c91906130f7565b6126a3565b600101611443565b505050505050565b5f805f805f805f6114c25f896111e4565b959e949d50929b5090995097509550909350915050565b5f6114e382612558565b6001600160a01b03939093165f90815260029093016020525050604090205460ff1690565b60366020525f908152604090208054819061152290613642565b80601f016020809104026020016040519081016040528092919081815260200182805461154e90613642565b80156115995780601f1061157057610100808354040283529160200191611599565b820191905f5260205f20905b81548152906001019060200180831161157c57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6112d882612886565b6026546040516304f65f8b60e21b81523060048201526001600160a01b038481166024830152604482018490525f9283928392839216906313d97e2c906064016040805180830381865afa158015611619573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061163d91906135de565b909450925050505b9250929050565b6001600160a01b0381165f90815260086020908152604080832080548251818502810185019093528083526060949384939291908301828280156116b757602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611699575b505050505090505f815190505f8167ffffffffffffffff8111156116dd576116dd613470565b604051908082528060200260200182016040528015611706578160200160208202803683370190505b5090505f5b8281101561179c575f6117368583815181106117295761172961362e565b6020026020010151612558565b805490915060ff1615611793578482815181106117555761175561362e565b602002602001015183878151811061176f5761176f61362e565b6001600160a01b03909216602092830291909101909101526117908661368e565b95505b5060010161170b565b5092835250909392505050565b6001600160a01b0382165f9081526035602052604081205481906117d6906001600160601b0316846125f1565b9695505050505050565b6060600d80548060200260200160405190810160405280929190818152602001828054801561183657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611818575b5050505050905090565b6060815f8167ffffffffffffffff81111561185d5761185d613470565b604051908082528060200260200182016040528015611886578160200160208202803683370190505b5090505f5b828110156113eb576118c38686838181106118a8576118a861362e565b90506020020160208101906118bd91906130f7565b336129ba565b60148111156118d4576118d46135ca565b8282815181106118e6576118e661362e565b602090810291909101015260010161188b565b602654604051630779996560e11b81523060048201526001600160a01b0385811660248301528481166044830152606482018490525f928392839283921690630ef332ca906084016040805180830381865afa15801561195b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197f91906135de565b909890975095505050505050565b5f6119c160405180604001604052806012815260200171637265617465506f6f6c28737472696e672960701b8152506124a8565b81515f036119e25760405163522e397360e11b815260040160405180910390fd5b603780545f919082906119fd906001600160601b03166136a6565b82546001600160601b038083166101009490940a848102910219909116179092555f90815260366020526040902090915080611a39858261370f565b5060028101805460ff191660011790556040516001600160601b038316907fc419386a8582a5374f4db03fdbb9fd99c73ef32d6ce9fc3a8c249e97bf31f9af90611a849087906137cb565b60405180910390a25092915050565b611ad16040518060400160405280602081526020017f72656d6f7665506f6f6c4d61726b65742875696e7439362c61646472657373298152506124a8565b6001600160601b038216611af857604051630203217b60e61b815260040160405180910390fd5b5f611b0383836112bd565b5f8181526009602052604090205490915060ff16611b4e576040516338ddb96b60e11b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c8c565b6001600160601b0383165f908152603660205260408120600101805490915b81811015611c5b57846001600160a01b0316838281548110611b9157611b9161362e565b5f918252602090912001546001600160a01b031603611c535782611bb66001846137dd565b81548110611bc657611bc661362e565b905f5260205f20015f9054906101000a90046001600160a01b0316838281548110611bf357611bf361362e565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b0316021790555082805480611c2e57611c2e6137f0565b5f8281526020902081015f1990810180546001600160a01b0319169055019055611c5b565b600101611b6d565b505f83815260096020526040808220805460ff199081168255600182018490556003820180549091169055600481018390556005810183905560060180546cffffffffffffffffffffffffff19169055516001600160a01b038616916001600160601b038816917fc8bef274db6d8c804aba68a69e64268bcfe7dd0aead2efcec0cac73a2df56e129190a35050505050565b5f336001600160a01b03841614801590611d2a57506001600160a01b0383165f908152602c6020908152604080832033845290915290205460ff16155b15611d48576040516337248ad960e01b815260040160405180910390fd5b611d5282846129ba565b6014811115610c3257610c326135ca565b5f80611d6f5f846125f1565b95945050505050565b6008602052815f5260405f208181548110611d91575f80fd5b5f918252602090912001546001600160a01b03169150829050565b611db582612a8d565b335f908152602c602090815260408083206001600160a01b038616845290915290205481151560ff909116151503611e2f5760405162461bcd60e51b815260206004820152601b60248201527f44656c65676174696f6e2073746174757320756e6368616e67656400000000006044820152606401610c8c565b611e3a338383612adb565b5050565b6001600160a01b0382165f90815260296020526040812081836008811115611e6857611e686135ca565b815260208101919091526040015f205460ff169392505050565b5f611e8e826008612b47565b6040516361bfb47160e11b815233600482015282905f90819081906001600160a01b0385169063c37f68e290602401608060405180830381865afa158015611ed8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611efc9190613804565b50925092509250825f14611f525760405162461bcd60e51b815260206004820152601960248201527f6765744163636f756e74536e617073686f74206661696c6564000000000000006044820152606401610c8c565b8015611f64576117d6600c600261257a565b5f611f70873385612b91565b90508015611f9057611f85600e600383612c38565b979650505050505050565b5f611f9a86612558565b335f90815260028201602052604090205490915060ff16611fc2575f98975050505050505050565b335f9081526002820160209081526040808320805460ff1916905560089091528120805490915b818110156120d757886001600160a01b031683828154811061200d5761200d61362e565b5f918252602090912001546001600160a01b0316036120cf57826120326001846137dd565b815481106120425761204261362e565b905f5260205f20015f9054906101000a90046001600160a01b031683828154811061206f5761206f61362e565b905f5260205f20015f6101000a8154816001600160a01b0302191690836001600160a01b03160217905550828054806120aa576120aa6137f0565b5f8281526020902081015f1990810180546001600160a01b03191690550190556120d7565b600101611fe9565b8181106120e6576120e6613837565b60405133906001600160a01b038b16907fe699a64c18b07ac5b7301aa273f36a2287239eb9501d81950672794afba29a0d905f90a35f9b9a5050505050505050505050565b6001600160a01b0382165f9081526008602090815260408083208054825181850281018501909352808352849383018282801561218f57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612171575b50939450505050506001600160601b038316158015906121c557506001600160a01b0384165f9081526016602052604090205415155b156121d3575f9150506112d8565b5f5b81518110156122af575f8282815181106121f1576121f161362e565b602002602001015190505f61220686836112bd565b5f81815260096020526040902060060154909150600160601b900460ff166122a5576040516395dd919360e01b81526001600160a01b0388811660048301525f91908416906395dd919390602401602060405180830381865afa15801561226f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612293919061384b565b11156122a5575f9450505050506112d8565b50506001016121d5565b506001949350505050565b6037546001600160601b0390811690821611156122f557604051632db8671b60e11b81526001600160601b0382166004820152602401610c8c565b335f908152603560205260409020546001600160601b039081169082160361233057604051631c9d4f3960e31b815260040160405180910390fd5b6001600160601b0381161580159061236357506001600160601b0381165f9081526036602052604090206002015460ff16155b1561238c57604051632da4cc0560e01b81526001600160601b0382166004820152602401610c8c565b612396338261212b565b6123b35760405163592ec11d60e01b815260040160405180910390fd5b335f818152603560209081526040918290205491516001600160601b03928316815291841692917f9181876220501cdac3aa7278fd34e9bd150c30a27b6ed95458fe859761b071f7910160405180910390a3335f81815260356020526040812080546bffffffffffffffffffffffff19166001600160601b0385161790559081906124419082808080612cb7565b9193509091505f905082601481111561245c5761245c6135ca565b14158061246857505f81115b156124a35781601481111561247f5761247f6135ca565b60405163c978466160e01b8152600481019190915260248101829052604401610c8c565b505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906124da9033908590600401613862565b602060405180830381865afa1580156124f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125199190613885565b6125555760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610c8c565b50565b5f60095f6125665f856112bd565b81526020019081526020015f209050919050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa08360148111156125ae576125ae6135ca565b83601a8111156125c0576125c06135ca565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610c3257610c326135ca565b6001600160601b0382165f818152603660205260408120909182918291829015806126215750600282015460ff16155b156126365761262f86612558565b9050612685565b5f61264188886112bd565b5f81815260096020526040902080549192509060ff1615801561266d57506002840154610100900460ff165b6126775780612680565b61268088612558565b925050505b80600101548160040154826005015494509450945050509250925092565b6001600160601b0382166126ca57604051630203217b60e61b815260040160405180910390fd5b6037546001600160601b03908116908316111561270557604051632db8671b60e11b81526001600160601b0383166004820152602401610c8c565b6001600160601b0382165f9081526036602052604090206002015460ff1661274b57604051632da4cc0560e01b81526001600160601b0383166004820152602401610c8c565b5f6127565f836112bd565b5f8181526009602052604090205490915060ff16612787576040516386dccab760e01b815260040160405180910390fd5b61279183836112bd565b5f8181526009602052604090205490915060ff16156127dd5760405163d9d72f2b60e01b81526001600160601b03841660048201526001600160a01b0383166024820152604401610c8c565b5f8181526009602090815260408083206006810180546bffffffffffffffffffffffff19166001600160601b038916908117909155815460ff19166001908117835581865260368552838620810180549182018155865293852090930180546001600160a01b0319166001600160a01b038816908117909155915190939192917f2159e9508e372ac69e1047a124c5478445206066e5d7df7e4214a1986cd78c8091a350505050565b5f6128c56040518060400160405280601781526020017f5f737570706f72744d61726b65742861646472657373290000000000000000008152506124a8565b6128ce82612558565b5460ff16156128e3576112d8600a601161257a565b816001600160a01b0316633d9ea3a16040518163ffffffff1660e01b8152600401602060405180830381865afa15801561291f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129439190613885565b505f61294e83612558565b8054600160ff19918216811783556003830180549092169091555f90820155905061297883612d80565b61298183612e56565b6040516001600160a01b038416907fcf583bb0c569eb967f806b11601c4cb93c10310485c67add5f8362c2f212321f905f90a25f610c32565b5f6129c6836007612b47565b5f6129d084612558565b90506129db81612f18565b6001600160a01b0383165f90815260028201602052604090205460ff1615612a06575f9150506112d8565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b6001600160a01b0381166125555760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610c8c565b6001600160a01b038381165f818152602c6020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fcb325b7784f78486e42849c7a50b8c5ee008d00cd90e108a58912c0fcb6288b4910160405180910390a3505050565b612b518282611e3e565b15611e3a5760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610c8c565b5f612ba3612b9e85612558565b612f18565b612bac84612558565b6001600160a01b0384165f908152600291909101602052604090205460ff16612bd657505f610c32565b5f80612be58587865f80612cb7565b9193509091505f9050826014811115612c0057612c006135ca565b14612c2057816014811115612c1757612c176135ca565b92505050610c32565b8015612c2d576004612c17565b5f9695505050505050565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0846014811115612c6c57612c6c6135ca565b84601a811115612c7e57612c7e6135ca565b604080519283526020830191909152810184905260600160405180910390a1836014811115612caf57612caf6135ca565b949350505050565b5f808080846001811115612ccd57612ccd6135ca565b03612cdb57612cdb88612f5d565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e90612d199030908f908f908f908f908f906004016138a0565b606060405180830381865afa158015612d34573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d5891906138db565b925092509250826014811115612d7057612d706135ca565b9b919a5098509650505050505050565b600d545f5b81811015612e0357826001600160a01b0316600d8281548110612daa57612daa61362e565b5f918252602090912001546001600160a01b031603612dfb5760405162461bcd60e51b815260206004820152600d60248201526c185b1c9958591e481859191959609a1b6044820152606401610c8c565b600101612d85565b5050600d80546001810182555f919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b0392909216919091179055565b5f612e5f61307b565b6001600160a01b0383165f908152601060209081526040808320601190925282208154939450909290916001600160e01b039091169003612eba5781546001600160e01b0319166ec097ce7bc90715b34b9f10000000001782555b80546001600160e01b03165f03612eeb5780546001600160e01b0319166ec097ce7bc90715b34b9f10000000001781555b805463ffffffff909316600160e01b026001600160e01b0393841681179091558154909216909117905550565b805460ff166125555760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610c8c565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015612fd357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612fb5575b505083519394505f925050505b8181101561307457836001600160a01b031663a9c3cab18483815181106130095761300961362e565b60200260200101516040518263ffffffff1660e01b815260040161303c91906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015613053575f80fd5b505af1158015613065573d5f803e3d5ffd5b50505050806001019050612fe0565b5050505050565b5f6130af4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b8152506130b4565b905090565b5f8164010000000084106130db5760405162461bcd60e51b8152600401610c8c91906137cb565b509192915050565b6001600160a01b0381168114612555575f80fd5b5f60208284031215613107575f80fd5b8135610c32816130e3565b5f8060408385031215613123575f80fd5b823561312e816130e3565b9150602083013561313e816130e3565b809150509250929050565b5f805f806080858703121561315c575f80fd5b8435613167816130e3565b93506020850135613177816130e3565b92506040850135613187816130e3565b9396929550929360600135925050565b5f805f606084860312156131a9575f80fd5b83356131b4816130e3565b925060208401356131c4816130e3565b91506040840135600281106131d7575f80fd5b809150509250925092565b80356001600160601b03811681146131f8575f80fd5b919050565b5f806040838503121561320e575f80fd5b61312e836131e2565b5f60208284031215613227575f80fd5b5035919050565b5f6020828403121561323e575f80fd5b610c32826131e2565b602080825282518282018190525f9190848201906040850190845b818110156132875783516001600160a01b031683529284019291840191600101613262565b50909695505050505050565b5f8083601f8401126132a3575f80fd5b50813567ffffffffffffffff8111156132ba575f80fd5b6020830191508360208260051b8501011115611645575f80fd5b5f805f80604085870312156132e7575f80fd5b843567ffffffffffffffff808211156132fe575f80fd5b61330a88838901613293565b90965094506020870135915080821115613322575f80fd5b5061332f87828801613293565b95989497509550505050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61337b606083018661333b565b931515602083015250901515604090910152919050565b5f80604083850312156133a3575f80fd5b82356133ae816130e3565b946020939093013593505050565b5f80602083850312156133cd575f80fd5b823567ffffffffffffffff8111156133e3575f80fd5b6133ef85828601613293565b90969095509350505050565b602080825282518282018190525f9190848201906040850190845b8181101561328757835183529284019291840191600101613416565b5f805f60608486031215613444575f80fd5b833561344f816130e3565b9250602084013561345f816130e3565b929592945050506040919091013590565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215613494575f80fd5b813567ffffffffffffffff808211156134ab575f80fd5b818401915084601f8301126134be575f80fd5b8135818111156134d0576134d0613470565b604051601f8201601f19908116603f011681019083821181831017156134f8576134f8613470565b81604052828152876020848701011115613510575f80fd5b826020860160208301375f928101602001929092525095945050505050565b8015158114612555575f80fd5b5f806040838503121561354d575f80fd5b8235613558816130e3565b9150602083013561313e8161352f565b5f8060408385031215613579575f80fd5b8235613584816130e3565b915060208301356009811061313e575f80fd5b5f80604083850312156135a8575f80fd5b82356135b3816130e3565b91506135c1602084016131e2565b90509250929050565b634e487b7160e01b5f52602160045260245ffd5b5f80604083850312156135ef575f80fd5b505080516020909101519092909150565b6002811061361c57634e487b7160e01b5f52602160045260245ffd5b9052565b602081016112d88284613600565b634e487b7160e01b5f52603260045260245ffd5b600181811c9082168061365657607f821691505b60208210810361367457634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52601160045260245ffd5b5f6001820161369f5761369f61367a565b5060010190565b5f6001600160601b038083168181036136c1576136c161367a565b6001019392505050565b601f8211156124a357805f5260205f20601f840160051c810160208510156136f05750805b601f840160051c820191505b81811015613074575f81556001016136fc565b815167ffffffffffffffff81111561372957613729613470565b61373d816137378454613642565b846136cb565b602080601f831160018114613770575f84156137595750858301515b5f19600386901b1c1916600185901b1785556114a9565b5f85815260208120601f198616915b8281101561379e5788860151825594840194600190910190840161377f565b50858210156137bb57878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b602081525f610c32602083018461333b565b818103818111156112d8576112d861367a565b634e487b7160e01b5f52603160045260245ffd5b5f805f8060808587031215613817575f80fd5b505082516020840151604085015160609095015191969095509092509050565b634e487b7160e01b5f52600160045260245ffd5b5f6020828403121561385b575f80fd5b5051919050565b6001600160a01b03831681526040602082018190525f90612caf9083018461333b565b5f60208284031215613895575f80fd5b8151610c328161352f565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101611f8560a0830184613600565b5f805f606084860312156138ed575f80fd5b835192506020840151915060408401519050925092509256fe616464506f6f6c4d61726b6574732875696e7439365b5d2c616464726573735b5d29a264697066735822122058abb9325ca9755ea139c408f1749ca1e81f0e897c695239d1deb995050db88a64736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This facet contains all the methods related to the market's management in the pool", @@ -2369,6 +2382,9 @@ "createPool(string)": { "notice": "Creates a new pool with the given label." }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "enterMarketBehalf(address,address)": { "notice": "Add assets to be included in account liquidity calculation" }, @@ -2544,7 +2560,7 @@ "storageLayout": { "storage": [ { - "astId": 4875, + "astId": 9780, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "admin", "offset": 0, @@ -2552,7 +2568,7 @@ "type": "t_address" }, { - "astId": 4878, + "astId": 9783, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "pendingAdmin", "offset": 0, @@ -2560,7 +2576,7 @@ "type": "t_address" }, { - "astId": 4881, + "astId": 9786, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "comptrollerImplementation", "offset": 0, @@ -2568,7 +2584,7 @@ "type": "t_address" }, { - "astId": 4884, + "astId": 9789, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -2576,15 +2592,15 @@ "type": "t_address" }, { - "astId": 4891, + "astId": 9796, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)3797" + "type": "t_contract(ResilientOracleInterface)8467" }, { - "astId": 4894, + "astId": 9799, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "closeFactorMantissa", "offset": 0, @@ -2592,7 +2608,7 @@ "type": "t_uint256" }, { - "astId": 4897, + "astId": 9802, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -2600,7 +2616,7 @@ "type": "t_uint256" }, { - "astId": 4900, + "astId": 9805, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "maxAssets", "offset": 0, @@ -2608,23 +2624,23 @@ "type": "t_uint256" }, { - "astId": 4907, + "astId": 9812, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)40234)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)" }, { - "astId": 4941, + "astId": 9846, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)14658,t_struct(Market)4934_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)" }, { - "astId": 4944, + "astId": 9849, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "pauseGuardian", "offset": 0, @@ -2632,7 +2648,7 @@ "type": "t_address" }, { - "astId": 4947, + "astId": 9852, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -2640,7 +2656,7 @@ "type": "t_bool" }, { - "astId": 4950, + "astId": 9855, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -2648,7 +2664,7 @@ "type": "t_bool" }, { - "astId": 4953, + "astId": 9858, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "transferGuardianPaused", "offset": 22, @@ -2656,7 +2672,7 @@ "type": "t_bool" }, { - "astId": 4956, + "astId": 9861, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -2664,7 +2680,7 @@ "type": "t_bool" }, { - "astId": 4961, + "astId": 9866, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "mintGuardianPaused", "offset": 0, @@ -2672,7 +2688,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 4966, + "astId": 9871, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -2680,15 +2696,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 4978, + "astId": 9883, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)40234)dyn_storage" + "type": "t_array(t_contract(VToken)58633)dyn_storage" }, { - "astId": 4981, + "astId": 9886, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusRate", "offset": 0, @@ -2696,7 +2712,7 @@ "type": "t_uint256" }, { - "astId": 4986, + "astId": 9891, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusSpeeds", "offset": 0, @@ -2704,23 +2720,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 4992, + "astId": 9897, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)4973_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 4998, + "astId": 9903, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)4973_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 5005, + "astId": 9910, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusSupplierIndex", "offset": 0, @@ -2728,7 +2744,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 5012, + "astId": 9917, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -2736,7 +2752,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 5017, + "astId": 9922, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusAccrued", "offset": 0, @@ -2744,15 +2760,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5021, + "astId": 9926, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)33333" + "type": "t_contract(VAIControllerInterface)51683" }, { - "astId": 5026, + "astId": 9931, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "mintedVAIs", "offset": 0, @@ -2760,7 +2776,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5029, + "astId": 9934, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "vaiMintRate", "offset": 0, @@ -2768,7 +2784,7 @@ "type": "t_uint256" }, { - "astId": 5032, + "astId": 9937, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -2776,7 +2792,7 @@ "type": "t_bool" }, { - "astId": 5034, + "astId": 9939, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -2784,7 +2800,7 @@ "type": "t_bool" }, { - "astId": 5037, + "astId": 9942, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "protocolPaused", "offset": 2, @@ -2792,7 +2808,7 @@ "type": "t_bool" }, { - "astId": 5040, + "astId": 9945, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusVAIRate", "offset": 0, @@ -2800,7 +2816,7 @@ "type": "t_uint256" }, { - "astId": 5046, + "astId": 9951, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -2808,7 +2824,7 @@ "type": "t_uint256" }, { - "astId": 5048, + "astId": 9953, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "vaiVaultAddress", "offset": 0, @@ -2816,7 +2832,7 @@ "type": "t_address" }, { - "astId": 5050, + "astId": 9955, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "releaseStartBlock", "offset": 0, @@ -2824,7 +2840,7 @@ "type": "t_uint256" }, { - "astId": 5052, + "astId": 9957, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "minReleaseAmount", "offset": 0, @@ -2832,7 +2848,7 @@ "type": "t_uint256" }, { - "astId": 5058, + "astId": 9963, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "borrowCapGuardian", "offset": 0, @@ -2840,7 +2856,7 @@ "type": "t_address" }, { - "astId": 5063, + "astId": 9968, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "borrowCaps", "offset": 0, @@ -2848,7 +2864,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5069, + "astId": 9974, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "treasuryGuardian", "offset": 0, @@ -2856,7 +2872,7 @@ "type": "t_address" }, { - "astId": 5072, + "astId": 9977, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "treasuryAddress", "offset": 0, @@ -2864,7 +2880,7 @@ "type": "t_address" }, { - "astId": 5075, + "astId": 9980, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "treasuryPercent", "offset": 0, @@ -2872,7 +2888,7 @@ "type": "t_uint256" }, { - "astId": 5083, + "astId": 9988, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -2880,7 +2896,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5088, + "astId": 9993, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "lastContributorBlock", "offset": 0, @@ -2888,7 +2904,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5093, + "astId": 9998, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "liquidatorContract", "offset": 0, @@ -2896,15 +2912,15 @@ "type": "t_address" }, { - "astId": 5099, + "astId": 10004, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)4858" + "type": "t_contract(ComptrollerLensInterface)9761" }, { - "astId": 5107, + "astId": 10012, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "supplyCaps", "offset": 0, @@ -2912,7 +2928,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5113, + "astId": 10018, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "accessControl", "offset": 0, @@ -2920,7 +2936,7 @@ "type": "t_address" }, { - "astId": 5120, + "astId": 10025, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_actionPaused", "offset": 0, @@ -2928,7 +2944,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 5128, + "astId": 10033, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -2936,7 +2952,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5133, + "astId": 10038, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -2944,7 +2960,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 5143, + "astId": 10048, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "approvedDelegates", "offset": 0, @@ -2952,7 +2968,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 5151, + "astId": 10056, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -2960,23 +2976,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 5170, + "astId": 10075, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)5159_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)" }, { - "astId": 5175, + "astId": 10080, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)5165_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)" }, { - "astId": 5178, + "astId": 10083, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "_facetAddresses", "offset": 0, @@ -2984,15 +3000,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 5185, + "astId": 10090, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)30511" + "type": "t_contract(IPrime)42902" }, { - "astId": 5195, + "astId": 10100, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -3000,7 +3016,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 5201, + "astId": 10106, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "xvs", "offset": 0, @@ -3008,7 +3024,7 @@ "type": "t_address" }, { - "astId": 5204, + "astId": 10109, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "xvsVToken", "offset": 0, @@ -3016,7 +3032,7 @@ "type": "t_address" }, { - "astId": 5226, + "astId": 10131, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "userPoolId", "offset": 0, @@ -3024,15 +3040,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 5232, + "astId": 10137, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)5221_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)10126_storage)" }, { - "astId": 5235, + "astId": 10140, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "lastPoolId", "offset": 0, @@ -3040,7 +3056,7 @@ "type": "t_uint96" }, { - "astId": 5243, + "astId": 10148, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -3048,12 +3064,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 5246, + "astId": 10151, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 10158, + "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)8437" } ], "types": { @@ -3074,8 +3098,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)40234)dyn_storage": { - "base": "t_contract(VToken)40234", + "t_array(t_contract(VToken)58633)dyn_storage": { + "base": "t_contract(VToken)58633", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -3090,37 +3114,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)4858": { + "t_contract(ComptrollerLensInterface)9761": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)30511": { + "t_contract(IDeviationBoundedOracle)8437": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)42902": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)3797": { + "t_contract(ResilientOracleInterface)8467": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)33333": { + "t_contract(VAIControllerInterface)51683": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)40234": { + "t_contract(VToken)58633": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)40234)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)40234)dyn_storage" + "value": "t_array(t_contract(VToken)58633)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -3150,19 +3179,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)5165_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)5165_storage" + "value": "t_struct(FacetFunctionSelectors)10070_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)4973_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)4973_storage" + "value": "t_struct(VenusMarketState)9878_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -3178,12 +3207,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)5159_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)5159_storage" + "value": "t_struct(FacetAddressAndPosition)10064_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -3192,31 +3221,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)5221_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)10126_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)5221_storage" + "value": "t_struct(PoolData)10126_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)14658,t_struct(Market)4934_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)14658", + "key": "t_userDefinedValueType(PoolMarketId)19777", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)4934_storage" + "value": "t_struct(Market)9839_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)5159_storage": { + "t_struct(FacetAddressAndPosition)10064_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 5156, + "astId": 10061, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "facetAddress", "offset": 0, @@ -3224,7 +3253,7 @@ "type": "t_address" }, { - "astId": 5158, + "astId": 10063, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "functionSelectorPosition", "offset": 20, @@ -3234,12 +3263,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)5165_storage": { + "t_struct(FacetFunctionSelectors)10070_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 5162, + "astId": 10067, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "functionSelectors", "offset": 0, @@ -3247,7 +3276,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 5164, + "astId": 10069, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "facetAddressPosition", "offset": 0, @@ -3257,12 +3286,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)4934_storage": { + "t_struct(Market)9839_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 4910, + "astId": 9815, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isListed", "offset": 0, @@ -3270,7 +3299,7 @@ "type": "t_bool" }, { - "astId": 4913, + "astId": 9818, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -3278,7 +3307,7 @@ "type": "t_uint256" }, { - "astId": 4918, + "astId": 9823, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "accountMembership", "offset": 0, @@ -3286,7 +3315,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 4921, + "astId": 9826, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isVenus", "offset": 0, @@ -3294,7 +3323,7 @@ "type": "t_bool" }, { - "astId": 4924, + "astId": 9829, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -3302,7 +3331,7 @@ "type": "t_uint256" }, { - "astId": 4927, + "astId": 9832, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -3310,7 +3339,7 @@ "type": "t_uint256" }, { - "astId": 4930, + "astId": 9835, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "poolId", "offset": 0, @@ -3318,7 +3347,7 @@ "type": "t_uint96" }, { - "astId": 4933, + "astId": 9838, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isBorrowAllowed", "offset": 12, @@ -3328,12 +3357,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)5221_storage": { + "t_struct(PoolData)10126_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 5210, + "astId": 10115, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "label", "offset": 0, @@ -3341,7 +3370,7 @@ "type": "t_string_storage" }, { - "astId": 5214, + "astId": 10119, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "vTokens", "offset": 0, @@ -3349,7 +3378,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 5217, + "astId": 10122, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "isActive", "offset": 0, @@ -3357,7 +3386,7 @@ "type": "t_bool" }, { - "astId": 5220, + "astId": 10125, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -3367,12 +3396,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)4973_storage": { + "t_struct(VenusMarketState)9878_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 4969, + "astId": 9874, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "index", "offset": 0, @@ -3380,7 +3409,7 @@ "type": "t_uint224" }, { - "astId": 4972, + "astId": 9877, "contract": "contracts/Comptroller/Diamond/facets/MarketFacet.sol:MarketFacet", "label": "block", "offset": 28, @@ -3410,7 +3439,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)14658": { + "t_userDefinedValueType(PoolMarketId)19777": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bsctestnet/PolicyFacet.json b/deployments/bsctestnet/PolicyFacet.json index 70d654cc8..24d39052a 100644 --- a/deployments/bsctestnet/PolicyFacet.json +++ b/deployments/bsctestnet/PolicyFacet.json @@ -1,5 +1,5 @@ { - "address": "0xf8d94ef23c1188f8ab1009E56D558d7834d1F019", + "address": "0xDAfA77ED8b2CdF4dBE2D1aB27770eDE6A4a54463", "abi": [ { "inputs": [], @@ -655,6 +655,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -1755,28 +1768,28 @@ "type": "function" } ], - "transactionHash": "0x70c439c703c22ee5382beac74125f38594e4623853e82bef3a0302b2cbce0146", + "transactionHash": "0x7f6471fa2f95516732236c5f25b2591f19ec4eb8afcf8dd9d3853a7811ff6d31", "receipt": { "to": null, - "from": "0x33C6476F88eeA28D7E7900F759B4597704Ef95B7", - "contractAddress": "0xf8d94ef23c1188f8ab1009E56D558d7834d1F019", - "transactionIndex": 0, - "gasUsed": "2997657", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0xDAfA77ED8b2CdF4dBE2D1aB27770eDE6A4a54463", + "transactionIndex": 3, + "gasUsed": "3095497", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xf7ea65f0b2858d964b885753028179a585b3901aedbde2fd09bfa4d321095dc0", - "transactionHash": "0x70c439c703c22ee5382beac74125f38594e4623853e82bef3a0302b2cbce0146", + "blockHash": "0x1d8e7540846de3e9e890c7239e5193861d37fec905d1865e3980d6e11115b57b", + "transactionHash": "0x7f6471fa2f95516732236c5f25b2591f19ec4eb8afcf8dd9d3853a7811ff6d31", "logs": [], - "blockNumber": 70272818, - "cumulativeGasUsed": "2997657", + "blockNumber": 102773914, + "cumulativeGasUsed": "3491707", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 10, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"VenusBorrowSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"VenusSupplySpeedUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"supplySpeeds\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"borrowSpeeds\",\"type\":\"uint256[]\"}],\"name\":\"_setVenusSpeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getBorrowingPower\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the hooks used while transferring the assets\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setVenusSpeeds(address[],uint256[],uint256[])\":{\"details\":\"Allows the contract admin to set XVS speed for a market\",\"params\":{\"borrowSpeeds\":\"New XVS speed for borrow\",\"supplySpeeds\":\"New XVS speed for supply\",\"vTokens\":\"The market whose XVS speed to update\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"vToken\":\"The market to verify the borrow against\"},\"returns\":{\"_0\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"vToken\":\"Asset whose underlying is being borrowed\"}},\"getAccountLiquidity(address)\":{\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), account liquidity in excess of liquidation threshold requirements, account shortfall below liquidation threshold requirements)\"}},\"getBorrowingPower(address)\":{\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"}},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\",\"vTokenModify\":\"The market to hypothetically redeem/borrow in\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The amount of collateral token that will be seized\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"mintAllowed(address,address,uint256)\":{\"params\":{\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\",\"vToken\":\"The market to verify the mint against\"},\"returns\":{\"_0\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\",\"vToken\":\"Asset being minted\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"redeemTokens\":\"The number of vTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\",\"vToken\":\"The market to verify the redeem against\"},\"returns\":{\"_0\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\",\"vToken\":\"Asset being redeemed\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which borrowed the asset\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\",\"vToken\":\"The market to verify the repay against\"},\"returns\":{\"_0\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"payer\":\"The address repaying the borrow\",\"vToken\":\"Asset being repaid\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"The market to verify the transfer against\"},\"returns\":{\"_0\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"Asset being transferred\"}}},\"title\":\"PolicyFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedBorrowerVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a borrower\"},\"DistributedSupplierVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a supplier\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"VenusBorrowSpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new borrow-side XVS speed is calculated for a market\"},\"VenusSupplySpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new supply-side XVS speed is calculated for a market\"}},\"kind\":\"user\",\"methods\":{\"_setVenusSpeeds(address[],uint256[],uint256[])\":{\"notice\":\"Set XVS speed for a single market\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt liquidation threshold requirements\"},\"getBorrowingPower(address)\":{\"notice\":\"Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains all the external pre-hook functions related to vToken\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/PolicyFacet.sol\":\"PolicyFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/PolicyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IPolicyFacet } from \\\"../interfaces/IPolicyFacet.sol\\\";\\n\\nimport { XVSRewardsHelper } from \\\"./XVSRewardsHelper.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title PolicyFacet\\n * @author Venus\\n * @dev This facet contains all the hooks used while transferring the assets\\n * @notice This facet contract contains all the external pre-hook functions related to vToken\\n */\\ncontract PolicyFacet is IPolicyFacet, XVSRewardsHelper {\\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.MINT);\\n ensureListed(getCorePoolMarket(vToken));\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n require(supplyCap != 0, \\\"market supply cap is 0\\\");\\n\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n require(nextTotalSupply <= supplyCap, \\\"market supply cap reached\\\");\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, minter);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n // solhint-disable-next-line no-unused-vars\\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(minter, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.REDEEM);\\n\\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\\n if (allowed != uint256(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, redeemer);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\\n require(redeemTokens != 0 || redeemAmount == 0, \\\"redeemTokens zero\\\");\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.BORROW);\\n ensureListed(getCorePoolMarket(vToken));\\n poolBorrowAllowed(borrower, vToken);\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n require(borrowCap != 0, \\\"market borrow cap is 0\\\");\\n\\n if (!getCorePoolMarket(vToken).accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == vToken, \\\"sender must be vToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(VToken(vToken), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n }\\n\\n if (oracle.getUnderlyingPrice(vToken) == 0) {\\n return uint256(Error.PRICE_ERROR);\\n }\\n\\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\\n require(nextTotalBorrows <= borrowCap, \\\"market borrow cap reached\\\");\\n\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n updateVenusBorrowIndex(vToken, borrowIndex);\\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n // solhint-disable-next-line no-unused-vars\\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address vToken,\\n address payer, // solhint-disable-line no-unused-vars\\n address borrower,\\n uint256 repayAmount // solhint-disable-line no-unused-vars\\n ) external returns (uint256) {\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.REPAY);\\n ensureListed(getCorePoolMarket(vToken));\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n updateVenusBorrowIndex(vToken, borrowIndex);\\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address vToken,\\n address payer, // solhint-disable-line no-unused-vars\\n address borrower,\\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount\\n ) external view returns (uint256) {\\n checkProtocolPauseState();\\n\\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\\n return uint256(Error.UNAUTHORIZED);\\n }\\n\\n ensureListed(getCorePoolMarket(vTokenCollateral));\\n uint256 borrowBalance;\\n if (address(vTokenBorrowed) != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n } else {\\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\\n }\\n\\n if (isForcedLiquidationEnabled[vTokenBorrowed] || isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n return uint(Error.TOO_MUCH_REPAY);\\n }\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n borrower,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_LIQUIDATION_THRESHOLD\\n );\\n\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall == 0) {\\n return uint256(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n // The liquidator may not repay more than what is allowed by the closeFactor\\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\\n return uint256(Error.TOO_MUCH_REPAY);\\n }\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n * @param seizeTokens The amount of collateral token that will be seized\\n */\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral, // solhint-disable-line no-unused-vars\\n address liquidator,\\n address borrower,\\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = getCorePoolMarket(vTokenCollateral);\\n\\n // We've added VAIController as a borrowed token list check for seize\\n ensureListed(market);\\n\\n if (!market.accountMembership[borrower]) {\\n return uint256(Error.MARKET_NOT_COLLATERAL);\\n }\\n\\n if (address(vTokenBorrowed) != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n\\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\\n return uint256(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vTokenCollateral);\\n distributeSupplierVenus(vTokenCollateral, borrower);\\n distributeSupplierVenus(vTokenCollateral, liquidator);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\\n if (allowed != uint256(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, src);\\n distributeSupplierVenus(vToken, dst);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n */\\n // solhint-disable-next-line no-unused-vars\\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(src, vToken);\\n prime.accrueInterestAndUpdateScore(dst, vToken);\\n }\\n }\\n\\n /**\\n * @notice Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\\n * @param account The account get liquidity for\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) {\\n return _getAccountLiquidity(account, WeightFunction.USE_COLLATERAL_FACTOR);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt liquidation threshold requirements\\n * @param account The account get liquidity for\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of liquidation threshold requirements,\\n * account shortfall below liquidation threshold requirements)\\n */\\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\\n return _getAccountLiquidity(account, WeightFunction.USE_LIQUIDATION_THRESHOLD);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n return (uint256(err), liquidity, shortfall);\\n }\\n\\n // setter functionality\\n /**\\n * @notice Set XVS speed for a single market\\n * @dev Allows the contract admin to set XVS speed for a market\\n * @param vTokens The market whose XVS speed to update\\n * @param supplySpeeds New XVS speed for supply\\n * @param borrowSpeeds New XVS speed for borrow\\n */\\n function _setVenusSpeeds(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplySpeeds,\\n uint256[] calldata borrowSpeeds\\n ) external {\\n ensureAdmin();\\n\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n ensureNonzeroAddress(address(vTokens[i]));\\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @dev Internal function to set XVS speed for a single market\\n * @param vToken The market whose XVS speed to update\\n * @param supplySpeed New XVS speed for supply\\n * @param borrowSpeed New XVS speed for borrow\\n * @custom:event VenusSupplySpeedUpdated Emitted after the venus supply speed for a market is updated\\n * @custom:event VenusBorrowSpeedUpdated Emitted after the venus borrow speed for a market is updated\\n */\\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n ensureListed(getCorePoolMarket(address(vToken)));\\n\\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. XVS accrued properly for the old speed, and\\n // 2. XVS accrued at the new speed starts after this block.\\n\\n updateVenusSupplyIndex(address(vToken));\\n // Update speed and emit event\\n venusSupplySpeeds[address(vToken)] = supplySpeed;\\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. XVS accrued properly for the old speed, and\\n // 2. XVS accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n updateVenusBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @dev Checks if vToken borrowing is allowed in the account's entered pool\\n * Reverts if borrowing is not permitted\\n * @param account The address of the account whose borrow permission is being checked\\n * @param vToken The vToken market to check borrowing status for\\n * @custom:error BorrowNotAllowedInPool Reverts if borrowing is not allowed in the account's entered pool\\n * @custom:error InactivePool Reverts if borrowing in an inactive pool.\\n */\\n function poolBorrowAllowed(address account, address vToken) internal view {\\n uint96 userPool = userPoolId[account];\\n PoolMarketId index = getPoolMarketIndex(userPool, vToken);\\n if (!_poolMarkets[index].isBorrowAllowed) {\\n revert BorrowNotAllowedInPool();\\n }\\n if (userPool != corePoolId && !pools[userPool].isActive) {\\n revert InactivePool(userPool);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x80f1a0df314b19d4d657001edb84718a132abe2382d1ad33d4b06607f51932f4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\n\\n/**\\n * @title XVSRewardsHelper\\n * @author Venus\\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\\n */\\ncontract XVSRewardsHelper is FacetBase {\\n /// @notice Emitted when XVS is distributed to a borrower\\n event DistributedBorrowerVenus(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 venusDelta,\\n uint256 venusBorrowIndex\\n );\\n\\n /// @notice Emitted when XVS is distributed to a supplier\\n event DistributedSupplierVenus(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 venusDelta,\\n uint256 venusSupplyIndex\\n );\\n\\n /**\\n * @notice Accrue XVS to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n */\\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\\n if (deltaBlocks != 0 && borrowSpeed != 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \\\"224\\\");\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n borrowState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Accrue XVS to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n */\\n function updateVenusSupplyIndex(address vToken) internal {\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n uint256 supplySpeed = venusSupplySpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\\n if (deltaBlocks != 0 && supplySpeed != 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \\\"224\\\");\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n supplyState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute XVS to\\n */\\n function distributeSupplierVenus(address vToken, address supplier) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 supplyIndex = venusSupplyState[vToken].index;\\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\\n // Update supplier's index to the current index since we are distributing accrued XVS\\n venusSupplierIndex[vToken][supplier] = supplyIndex;\\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n // Multiply of supplierTokens and supplierDelta\\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\\n // Addition of supplierAccrued and supplierDelta\\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute XVS to\\n */\\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 borrowIndex = venusBorrowState[vToken].index;\\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\\n // Update borrowers's index to the current index since we are distributing accrued XVS\\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0xf356db714f7aada286380ee5092b0a3e3163428943cfb5561ded76597e1c0c15\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IPolicyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IPolicyFacet {\\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\\n\\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\\n\\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\\n\\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) external returns (uint256);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint256 repayAmount,\\n uint256 borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount\\n ) external view returns (uint256);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n uint256 seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external returns (uint256);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external;\\n\\n function transferAllowed(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external returns (uint256);\\n\\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\\n\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256, uint256, uint256);\\n\\n function _setVenusSpeeds(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplySpeeds,\\n uint256[] calldata borrowSpeeds\\n ) external;\\n\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall);\\n}\\n\",\"keccak256\":\"0x6fd69f4b22548e9288f7c025d501966ae4f83132693a8e33f1e35ed55151d111\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506135308061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106103e0575f3560e01c80637dc0d1d01161020b578063c5f956af1161011f578063e0f6123d116100b4578063eabe7d9111610084578063eabe7d91146109ef578063ead1a8a014610a02578063f445d70314610a15578063f851a44014610a42578063fa6331d814610a54575f80fd5b8063e0f6123d1461097a578063e37d4b791461099c578063e85a2960146109d3578063e8755446146109e6575f80fd5b8063d463654c116100ef578063d463654c1461093a578063da3d454c14610941578063dce1544914610954578063dcfbc0c714610967575f80fd5b8063c5f956af146108ee578063c7ee005e14610901578063d02f735114610914578063d3270f9914610927575f80fd5b8063a657e579116101a0578063bbb8864a11610170578063bbb8864a14610875578063bdcdc25814610894578063bec04f72146108a7578063bf32442d146108b0578063c5b4db55146108c1575f80fd5b8063a657e579146107e1578063b2eafc39146107f4578063b8324c7c14610807578063bb82aa5e14610862575f80fd5b80639254f5e5116101db5780639254f5e51461079057806394b2294b146107a357806396c99064146107ac5780639bb27d62146107ce575f80fd5b80637dc0d1d01461072f5780637fb8e8cd146107425780638a7dc1651461074f5780638c1ac18a1461076e575f80fd5b80634a584432116103025780635dd3fc9d116102975780636d35bf91116102675780636d35bf91146106ae578063719f701b146106c157806373769099146106ca578063765513831461070a5780637d172bd51461071c575f80fd5b80635dd3fc9d146106565780635ec88c79146106755780635fc7e71e146106885780636a56947e1461069b575f80fd5b806351dff989116102d257806351dff9891461060a578063528a174c1461061d57806352d84d1e146106305780635c77860514610643575f80fd5b80634a584432146105975780634d99c776146105b65780634e79238f146105c95780634ef4c3e1146105f7575f80fd5b806324a3d6221161037857806341a18d2c1161034857806341a18d2c1461053457806341c728b91461055e578063425fad581461057157806347ef3b3b14610584575f80fd5b806324a3d622146104e257806326782247146104f55780632bc7e29e146105085780634088c73e14610527575f80fd5b806310b98338116103b357806310b98338146104525780631ededc911461048f57806321af4569146104a457806324008a62146104cf575f80fd5b806302c3bcbb146103e457806304ef9d581461041657806308e0225c1461041f5780630db4b4e514610449575b5f80fd5b6104036103f2366004612edf565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61040360225481565b61040361042d366004612efa565b601360209081525f928352604080842090915290825290205481565b610403601d5481565b61047f610460366004612efa565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161040d565b6104a261049d366004612f31565b610a5d565b005b601e546104b7906001600160a01b031681565b6040516001600160a01b03909116815260200161040d565b6104036104dd366004612f88565b610ad5565b600a546104b7906001600160a01b031681565b6001546104b7906001600160a01b031681565b610403610516366004612edf565b60166020525f908152604090205481565b60185461047f9060ff1681565b610403610542366004612efa565b601260209081525f928352604080842090915290825290205481565b6104a261056c366004612fd6565b610b8c565b60185461047f9062010000900460ff1681565b6104a2610592366004613019565b610c03565b6104036105a5366004612edf565b601f6020525f908152604090205481565b6104036105c436600461309e565b610cdb565b6105dc6105d7366004612fd6565b610cfc565b6040805193845260208401929092529082015260600161040d565b6104036106053660046130b8565b610d36565b6104a2610618366004612fd6565b610f0e565b6105dc61062b366004612edf565b610f5a565b6104b761063e3660046130f6565b610f74565b6104a26106513660046130b8565b610f9c565b610403610664366004612edf565b602b6020525f908152604090205481565b6105dc610683366004612edf565b611012565b61040361069636600461310d565b611020565b6104a26106a9366004612f88565b611270565b6104a26106bc36600461310d565b611312565b610403601c5481565b6106f26106d8366004612edf565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161040d565b60185461047f90610100900460ff1681565b601b546104b7906001600160a01b031681565b6004546104b7906001600160a01b031681565b60395461047f9060ff1681565b61040361075d366004612edf565b60146020525f908152604090205481565b61047f61077c366004612edf565b602d6020525f908152604090205460ff1681565b6015546104b7906001600160a01b031681565b61040360075481565b6107bf6107ba36600461316d565b6113b4565b60405161040d939291906131b4565b6025546104b7906001600160a01b031681565b6037546106f2906001600160601b031681565b6020546104b7906001600160a01b031681565b61083e610815366004612edf565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161040d565b6002546104b7906001600160a01b031681565b610403610883366004612edf565b602a6020525f908152604090205481565b6104036108a2366004612f88565b611461565b61040360175481565b6033546001600160a01b03166104b7565b6108d66a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b03909116815260200161040d565b6021546104b7906001600160a01b031681565b6031546104b7906001600160a01b031681565b61040361092236600461310d565b6114ad565b6026546104b7906001600160a01b031681565b6106f25f81565b61040361094f3660046130b8565b611626565b6104b76109623660046131dd565b611995565b6003546104b7906001600160a01b031681565b61047f610988366004612edf565b60386020525f908152604090205460ff1681565b61083e6109aa366004612edf565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61047f6109e1366004613207565b6119c9565b61040360055481565b6104036109fd3660046130b8565b611a0d565b6104a2610a1036600461327e565b611a59565b61047f610a23366004612efa565b603260209081525f928352604080842090915290825290205460ff1681565b5f546104b7906001600160a01b031681565b610403601a5481565b6031546001600160a01b031615610ace576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610aa09086908990600401613311565b5f604051808303815f87803b158015610ab7575f80fd5b505af1158015610ac9573d5f803e3d5ffd5b505050505b5050505050565b5f610ade611b4e565b610ae9856003611b9e565b610afa610af586611bec565b611c0e565b5f6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b66919061332b565b90529050610b748682611c56565b610b7f868583611ded565b5f9150505b949350505050565b6031546001600160a01b031615610bfd576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610bcf9086908890600401613311565b5f604051808303815f87803b158015610be6575f80fd5b505af1158015610bf8573d5f803e3d5ffd5b505050505b50505050565b6031546001600160a01b031615610cd3576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610c469086908a90600401613311565b5f604051808303815f87803b158015610c5d575f80fd5b505af1158015610c6f573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610ca59087908a90600401613311565b5f604051808303815f87803b158015610cbc575f80fd5b505af1158015610cce573d5f803e3d5ffd5b505050505b505050505050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b5f805f805f80610d0f8a8a8a8a5f611f71565b925092509250826014811115610d2757610d27613342565b9a919950975095505050505050565b5f610d3f611b4e565b610d49845f611b9e565b610d55610af585611bec565b6001600160a01b0384165f9081526027602052604081205490819003610dbb5760405162461bcd60e51b815260206004820152601660248201527506d61726b657420737570706c792063617020697320360541b60448201526064015b60405180910390fd5b5f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1c919061332b565b90505f6040518060200160405280886001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e66573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8a919061332b565b905290505f610e9a82848861201e565b905083811115610eec5760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420737570706c79206361702072656163686564000000000000006044820152606401610db2565b610ef58861203e565b610eff88886121ab565b5f9450505050505b9392505050565b80151580610f1a575081155b610b8c5760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610db2565b5f805f610f67845f612349565b9250925092509193909250565b600d8181548110610f83575f80fd5b5f918252602090912001546001600160a01b0316905081565b6031546001600160a01b03161561100d576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610fdf9085908790600401613311565b5f604051808303815f87803b158015610ff6575f80fd5b505af1158015611008573d5f803e3d5ffd5b505050505b505050565b5f805f610f67846001612349565b5f611029611b4e565b611034866005611b9e565b6025546001600160a01b03161580159061105c57506025546001600160a01b03858116911614155b1561106957506001611267565b611075610af586611bec565b6015545f906001600160a01b0388811691161461110757611098610af588611bec565b6040516395dd919360e01b81526001600160a01b0385811660048301528816906395dd919390602401602060405180830381865afa1580156110dc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611100919061332b565b9050611176565b601554604051633c617c9160e11b81526001600160a01b038681166004830152909116906378c2f92290602401602060405180830381865afa15801561114f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611173919061332b565b90505b6001600160a01b0387165f908152602d602052604090205460ff16806111c057506001600160a01b038085165f908152603260209081526040808320938b168352929052205460ff165b156111de57808311156111d85760115b915050611267565b5f6111d0565b5f806111ee865f805f6001611f71565b9193509091505f905082601481111561120957611209613342565b1461122a5781601481111561122057611220613342565b9350505050611267565b805f03611238576003611220565b611252604051806020016040528060055481525084612381565b851115611260576011611220565b5f93505050505b95945050505050565b6031546001600160a01b031615610bfd576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906112b39086908890600401613311565b5f604051808303815f87803b1580156112ca575f80fd5b505af11580156112dc573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610bcf9085908890600401613311565b6031546001600160a01b031615610ace576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906113559085908990600401613311565b5f604051808303815f87803b15801561136c575f80fd5b505af115801561137e573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610aa09086908990600401613311565b60366020525f90815260409020805481906113ce90613356565b80601f01602080910402602001604051908101604052809291908181526020018280546113fa90613356565b80156114455780601f1061141c57610100808354040283529160200191611445565b820191905f5260205f20905b81548152906001019060200180831161142857829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f61146a611b4e565b611475856006611b9e565b5f611481868685612398565b90508015611490579050610b84565b6114998661203e565b6114a386866121ab565b610b7f86856121ab565b5f6114b6611b4e565b6114c1866004611b9e565b5f6114cb87611bec565b90506114d681611c0e565b6001600160a01b0384165f90815260028201602052604090205460ff166114fe5760136111d0565b6015546001600160a01b0387811691161461151f5761151f610af587611bec565b856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561155b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157f919061338e565b6001600160a01b0316876001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e8919061338e565b6001600160a01b0316146115fd5760026111d0565b6116068761203e565b61161087856121ab565b61161a87866121ab565b5f979650505050505050565b5f61162f611b4e565b61163a846002611b9e565b611646610af585611bec565b6116508385612431565b6001600160a01b0384165f908152601f6020526040812054908190036116b15760405162461bcd60e51b815260206004820152601660248201527506d61726b657420626f72726f772063617020697320360541b6044820152606401610db2565b6116ba85611bec565b6001600160a01b0385165f908152600291909101602052604090205460ff1661176f57336001600160a01b0386161461172d5760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba103132903b2a37b5b2b760591b6044820152606401610db2565b5f61173886866124f4565b90505f81601481111561174d5761174d613342565b1461176d5780601481111561176457611764613342565b92505050610f07565b505b6004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa1580156117b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117dd919061332b565b5f036117ed57600d915050610f07565b5f611857866001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561182d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611851919061332b565b856125c7565b9050818111156118a95760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610db2565b5f806118b887895f895f611f71565b9193509091505f90508260148111156118d3576118d3613342565b146118f5578160148111156118ea576118ea613342565b945050505050610f07565b80156119025760046118ea565b5f60405180602001604052808a6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561194a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196e919061332b565b9052905061197c8982611c56565b611987898983611ded565b5f9998505050505050505050565b6008602052815f5260405f2081815481106119ae575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f908152602960205260408120818360088111156119f3576119f3613342565b815260208101919091526040015f205460ff169392505050565b5f611a16611b4e565b611a21846001611b9e565b5f611a2d858585612398565b90508015611a3c579050610f07565b611a458561203e565b611a4f85856121ab565b5f95945050505050565b611a616125fc565b848381148015611a7057508082145b611aac5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610db2565b5f5b81811015610bf857611ae5888883818110611acb57611acb6133a9565b9050602002016020810190611ae09190612edf565b612646565b611b46888883818110611afa57611afa6133a9565b9050602002016020810190611b0f9190612edf565b878784818110611b2157611b216133a9565b90506020020135868685818110611b3a57611b3a6133a9565b90506020020135612694565b600101611aae565b60185462010000900460ff1615611b9c5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610db2565b565b611ba882826119c9565b15611be85760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610db2565b5050565b5f60095f611bfa5f85610cdb565b81526020019081526020015f209050919050565b805460ff16611c535760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610db2565b50565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611c8261280e565b83549091505f90611ca39063ffffffff80851691600160e01b900416612847565b90508015801590611cb357508215155b15611dc2575f611d22876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d1c919061332b565b87612880565b90505f611d2f838661289d565b90505f825f03611d4d5760405180602001604052805f815250611d57565b611d5782846128de565b604080516020810190915288546001600160e01b03168152909150611da090611d809083612921565b516040805180820190915260038152620c8c8d60ea1b602082015261294a565b6001600160e01b0316600160e01b63ffffffff87160217875550610cd3915050565b8015610cd357835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b601b546001600160a01b031615611e0657611e06612978565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b03909216908190559080158015611e6257506a0c097ce7bc90715b34b9f160241b8210155b15611e7857506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611e8e8585612847565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f91611ee791611ee1918a16906395dd919390602401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b83612aea565b6001600160a01b0387165f90815260146020526040902054909150611f0c90826125c7565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e90611fb79030908f908f908f908f908f906004016133bd565b606060405180830381865afa158015611fd2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ff69190613418565b92509250925082601481111561200e5761200e613342565b9b919a5098509650505050505050565b5f8061202a8585612b11565b905061126761203882612b37565b846125c7565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161206a61280e565b83549091505f9061208b9063ffffffff80851691600160e01b900416612847565b9050801580159061209b57508215155b15612181575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612101919061332b565b90505f61210e838661289d565b90505f825f0361212c5760405180602001604052805f815250612136565b61213682846128de565b604080516020810190915288546001600160e01b0316815290915061215f90611d809083612921565b6001600160e01b0316600160e01b63ffffffff87160217875550610ace915050565b8015610ace57835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b601b546001600160a01b0316156121c4576121c4612978565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b0390921690819055908015801561222057506a0c097ce7bc90715b34b9f160241b8210155b1561223657506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061224c8585612847565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f916122c091908816906370a0823190602401602060405180830381865afa15801561229c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee1919061332b565b6001600160a01b0386165f908152601460205260409020549091506122e590826125c7565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f805f805f8061235c885f805f8b611f71565b92509250925082601481111561237457612374613342565b9891975095509350505050565b5f8061238d8484612b11565b9050610b8481612b37565b5f6123a5610af585611bec565b6123ae84611bec565b6001600160a01b0384165f908152600291909101602052604090205460ff166123d857505f610f07565b5f806123e78587865f80611f71565b9193509091505f905082601481111561240257612402613342565b146124195781601481111561176457611764613342565b8015612426576004611764565b5f9695505050505050565b6001600160a01b0382165f908152603560205260408120546001600160601b03169061245d8284610cdb565b5f81815260096020526040902060060154909150600160601b900460ff16612498576040516305b80c7960e41b815260040160405180910390fd5b6001600160601b038216158015906124cb57506001600160601b0382165f9081526036602052604090206002015460ff16155b15610bfd57604051632da4cc0560e01b81526001600160601b0383166004820152602401610db2565b5f612500836007611b9e565b5f61250a84611bec565b905061251581611c0e565b6001600160a01b0383165f90815260028201602052604090205460ff1615612540575f915050610cf6565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b5f610f078383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612b4e565b5f546001600160a01b03163314611b9c5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610db2565b6001600160a01b038116611c535760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610db2565b6126a0610af584611bec565b6001600160a01b0383165f908152602b6020526040902054821461271c576126c78361203e565b6001600160a01b0383165f818152602b602052604090819020849055517fa9ff26899e4982e7634afa9f70115dcfb61a17d6e8cdd91aa837671d0ff40ba6906127139085815260200190565b60405180910390a25b6001600160a01b0383165f908152602a6020526040902054811461100d575f6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612782573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127a6919061332b565b905290506127b48482611c56565b6001600160a01b0384165f818152602a602052604090819020849055517f0c62c1bc89ec4c40dccb4d21543e782c5ba43897c0075d108d8964181ea3c51b906128009085815260200190565b60405180910390a250505050565b5f6128424360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612b87565b905090565b5f610f078383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612bae565b5f610f0761289684670de0b6b3a764000061289d565b8351612bdc565b5f610f0783836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612c0e565b60408051602081019091525f81526040518060200160405280612918612912866a0c097ce7bc90715b34b9f160241b61289d565b85612bdc565b90529392505050565b60408051602081019091525f81526040518060200160405280612918855f0151855f01516125c7565b5f81600160e01b84106129705760405162461bcd60e51b8152600401610db29190613443565b509192915050565b601c5415806129885750601c5443105b1561298f57565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156129d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129fd919061332b565b9050805f03612a0a575050565b5f80612a1843601c54612847565b90505f612a27601a548361289d565b9050808410612a3857809250612a3c565b8392505b601d54831015612a4d575050505050565b43601c55601b54612a6b906001600160a01b03878116911685612c5e565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ab7575f80fd5b5f6a0c097ce7bc90715b34b9f160241b612b0784845f015161289d565b610f079190613469565b60408051602081019091525f81526040518060200160405280612918855f01518561289d565b80515f90610cf690670de0b6b3a764000090613469565b5f80612b5a8486613488565b90508285821015612b7e5760405162461bcd60e51b8152600401610db29190613443565b50949350505050565b5f8164010000000084106129705760405162461bcd60e51b8152600401610db29190613443565b5f8184841115612bd15760405162461bcd60e51b8152600401610db29190613443565b50610b84838561349b565b5f610f0783836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612cb0565b5f831580612c1a575082155b15612c2657505f610f07565b5f612c3184866134ae565b905083612c3e8683613469565b148390612b7e5760405162461bcd60e51b8152600401610db29190613443565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261100d908490612cdb565b5f8183612cd05760405162461bcd60e51b8152600401610db29190613443565b50610b848385613469565b5f612d2f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612dae9092919063ffffffff16565b905080515f1480612d4f575080806020019051810190612d4f91906134c5565b61100d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610db2565b6060610b8484845f85855f80866001600160a01b03168587604051612dd391906134e4565b5f6040518083038185875af1925050503d805f8114612e0d576040519150601f19603f3d011682016040523d82523d5f602084013e612e12565b606091505b5091509150612e2387838387612e2e565b979650505050505050565b60608315612e9c5782515f03612e95576001600160a01b0385163b612e955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610db2565b5081610b84565b610b848383815115612eb15781518083602001fd5b8060405162461bcd60e51b8152600401610db29190613443565b6001600160a01b0381168114611c53575f80fd5b5f60208284031215612eef575f80fd5b8135610f0781612ecb565b5f8060408385031215612f0b575f80fd5b8235612f1681612ecb565b91506020830135612f2681612ecb565b809150509250929050565b5f805f805f60a08688031215612f45575f80fd5b8535612f5081612ecb565b94506020860135612f6081612ecb565b93506040860135612f7081612ecb565b94979396509394606081013594506080013592915050565b5f805f8060808587031215612f9b575f80fd5b8435612fa681612ecb565b93506020850135612fb681612ecb565b92506040850135612fc681612ecb565b9396929550929360600135925050565b5f805f8060808587031215612fe9575f80fd5b8435612ff481612ecb565b9350602085013561300481612ecb565b93969395505050506040820135916060013590565b5f805f805f8060c0878903121561302e575f80fd5b863561303981612ecb565b9550602087013561304981612ecb565b9450604087013561305981612ecb565b9350606087013561306981612ecb565b9598949750929560808101359460a0909101359350915050565b80356001600160601b0381168114613099575f80fd5b919050565b5f80604083850312156130af575f80fd5b612f1683613083565b5f805f606084860312156130ca575f80fd5b83356130d581612ecb565b925060208401356130e581612ecb565b929592945050506040919091013590565b5f60208284031215613106575f80fd5b5035919050565b5f805f805f60a08688031215613121575f80fd5b853561312c81612ecb565b9450602086013561313c81612ecb565b9350604086013561314c81612ecb565b9250606086013561315c81612ecb565b949793965091946080013592915050565b5f6020828403121561317d575f80fd5b610f0782613083565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6131c66060830186613186565b931515602083015250901515604090910152919050565b5f80604083850312156131ee575f80fd5b82356131f981612ecb565b946020939093013593505050565b5f8060408385031215613218575f80fd5b823561322381612ecb565b9150602083013560098110612f26575f80fd5b5f8083601f840112613246575f80fd5b50813567ffffffffffffffff81111561325d575f80fd5b6020830191508360208260051b8501011115613277575f80fd5b9250929050565b5f805f805f8060608789031215613293575f80fd5b863567ffffffffffffffff808211156132aa575f80fd5b6132b68a838b01613236565b909850965060208901359150808211156132ce575f80fd5b6132da8a838b01613236565b909650945060408901359150808211156132f2575f80fd5b506132ff89828a01613236565b979a9699509497509295939492505050565b6001600160a01b0392831681529116602082015260400190565b5f6020828403121561333b575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c9082168061336a57607f821691505b60208210810361338857634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561339e575f80fd5b8151610f0781612ecb565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c081016002831061340757634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f6060848603121561342a575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610f076020830184613186565b634e487b7160e01b5f52601160045260245ffd5b5f8261348357634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610cf657610cf6613455565b81810381811115610cf657610cf6613455565b8082028115828204841417610cf657610cf6613455565b5f602082840312156134d5575f80fd5b81518015158114610f07575f80fd5b5f82518060208501845e5f92019182525091905056fea26469706673582212207cd5f621d2b69e8b6c5d9a886845faa973f3a67a1195d459753ae549f728168064736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106103e0575f3560e01c80637dc0d1d01161020b578063c5f956af1161011f578063e0f6123d116100b4578063eabe7d9111610084578063eabe7d91146109ef578063ead1a8a014610a02578063f445d70314610a15578063f851a44014610a42578063fa6331d814610a54575f80fd5b8063e0f6123d1461097a578063e37d4b791461099c578063e85a2960146109d3578063e8755446146109e6575f80fd5b8063d463654c116100ef578063d463654c1461093a578063da3d454c14610941578063dce1544914610954578063dcfbc0c714610967575f80fd5b8063c5f956af146108ee578063c7ee005e14610901578063d02f735114610914578063d3270f9914610927575f80fd5b8063a657e579116101a0578063bbb8864a11610170578063bbb8864a14610875578063bdcdc25814610894578063bec04f72146108a7578063bf32442d146108b0578063c5b4db55146108c1575f80fd5b8063a657e579146107e1578063b2eafc39146107f4578063b8324c7c14610807578063bb82aa5e14610862575f80fd5b80639254f5e5116101db5780639254f5e51461079057806394b2294b146107a357806396c99064146107ac5780639bb27d62146107ce575f80fd5b80637dc0d1d01461072f5780637fb8e8cd146107425780638a7dc1651461074f5780638c1ac18a1461076e575f80fd5b80634a584432116103025780635dd3fc9d116102975780636d35bf91116102675780636d35bf91146106ae578063719f701b146106c157806373769099146106ca578063765513831461070a5780637d172bd51461071c575f80fd5b80635dd3fc9d146106565780635ec88c79146106755780635fc7e71e146106885780636a56947e1461069b575f80fd5b806351dff989116102d257806351dff9891461060a578063528a174c1461061d57806352d84d1e146106305780635c77860514610643575f80fd5b80634a584432146105975780634d99c776146105b65780634e79238f146105c95780634ef4c3e1146105f7575f80fd5b806324a3d6221161037857806341a18d2c1161034857806341a18d2c1461053457806341c728b91461055e578063425fad581461057157806347ef3b3b14610584575f80fd5b806324a3d622146104e257806326782247146104f55780632bc7e29e146105085780634088c73e14610527575f80fd5b806310b98338116103b357806310b98338146104525780631ededc911461048f57806321af4569146104a457806324008a62146104cf575f80fd5b806302c3bcbb146103e457806304ef9d581461041657806308e0225c1461041f5780630db4b4e514610449575b5f80fd5b6104036103f2366004612edf565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61040360225481565b61040361042d366004612efa565b601360209081525f928352604080842090915290825290205481565b610403601d5481565b61047f610460366004612efa565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161040d565b6104a261049d366004612f31565b610a5d565b005b601e546104b7906001600160a01b031681565b6040516001600160a01b03909116815260200161040d565b6104036104dd366004612f88565b610ad5565b600a546104b7906001600160a01b031681565b6001546104b7906001600160a01b031681565b610403610516366004612edf565b60166020525f908152604090205481565b60185461047f9060ff1681565b610403610542366004612efa565b601260209081525f928352604080842090915290825290205481565b6104a261056c366004612fd6565b610b8c565b60185461047f9062010000900460ff1681565b6104a2610592366004613019565b610c03565b6104036105a5366004612edf565b601f6020525f908152604090205481565b6104036105c436600461309e565b610cdb565b6105dc6105d7366004612fd6565b610cfc565b6040805193845260208401929092529082015260600161040d565b6104036106053660046130b8565b610d36565b6104a2610618366004612fd6565b610f0e565b6105dc61062b366004612edf565b610f5a565b6104b761063e3660046130f6565b610f74565b6104a26106513660046130b8565b610f9c565b610403610664366004612edf565b602b6020525f908152604090205481565b6105dc610683366004612edf565b611012565b61040361069636600461310d565b611020565b6104a26106a9366004612f88565b611270565b6104a26106bc36600461310d565b611312565b610403601c5481565b6106f26106d8366004612edf565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161040d565b60185461047f90610100900460ff1681565b601b546104b7906001600160a01b031681565b6004546104b7906001600160a01b031681565b60395461047f9060ff1681565b61040361075d366004612edf565b60146020525f908152604090205481565b61047f61077c366004612edf565b602d6020525f908152604090205460ff1681565b6015546104b7906001600160a01b031681565b61040360075481565b6107bf6107ba36600461316d565b6113b4565b60405161040d939291906131b4565b6025546104b7906001600160a01b031681565b6037546106f2906001600160601b031681565b6020546104b7906001600160a01b031681565b61083e610815366004612edf565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161040d565b6002546104b7906001600160a01b031681565b610403610883366004612edf565b602a6020525f908152604090205481565b6104036108a2366004612f88565b611461565b61040360175481565b6033546001600160a01b03166104b7565b6108d66a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b03909116815260200161040d565b6021546104b7906001600160a01b031681565b6031546104b7906001600160a01b031681565b61040361092236600461310d565b6114ad565b6026546104b7906001600160a01b031681565b6106f25f81565b61040361094f3660046130b8565b611626565b6104b76109623660046131dd565b611995565b6003546104b7906001600160a01b031681565b61047f610988366004612edf565b60386020525f908152604090205460ff1681565b61083e6109aa366004612edf565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61047f6109e1366004613207565b6119c9565b61040360055481565b6104036109fd3660046130b8565b611a0d565b6104a2610a1036600461327e565b611a59565b61047f610a23366004612efa565b603260209081525f928352604080842090915290825290205460ff1681565b5f546104b7906001600160a01b031681565b610403601a5481565b6031546001600160a01b031615610ace576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610aa09086908990600401613311565b5f604051808303815f87803b158015610ab7575f80fd5b505af1158015610ac9573d5f803e3d5ffd5b505050505b5050505050565b5f610ade611b4e565b610ae9856003611b9e565b610afa610af586611bec565b611c0e565b5f6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b42573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b66919061332b565b90529050610b748682611c56565b610b7f868583611ded565b5f9150505b949350505050565b6031546001600160a01b031615610bfd576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610bcf9086908890600401613311565b5f604051808303815f87803b158015610be6575f80fd5b505af1158015610bf8573d5f803e3d5ffd5b505050505b50505050565b6031546001600160a01b031615610cd3576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610c469086908a90600401613311565b5f604051808303815f87803b158015610c5d575f80fd5b505af1158015610c6f573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610ca59087908a90600401613311565b5f604051808303815f87803b158015610cbc575f80fd5b505af1158015610cce573d5f803e3d5ffd5b505050505b505050505050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b5f805f805f80610d0f8a8a8a8a5f611f71565b925092509250826014811115610d2757610d27613342565b9a919950975095505050505050565b5f610d3f611b4e565b610d49845f611b9e565b610d55610af585611bec565b6001600160a01b0384165f9081526027602052604081205490819003610dbb5760405162461bcd60e51b815260206004820152601660248201527506d61726b657420737570706c792063617020697320360541b60448201526064015b60405180910390fd5b5f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610df8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e1c919061332b565b90505f6040518060200160405280886001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e66573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e8a919061332b565b905290505f610e9a82848861201e565b905083811115610eec5760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420737570706c79206361702072656163686564000000000000006044820152606401610db2565b610ef58861203e565b610eff88886121ab565b5f9450505050505b9392505050565b80151580610f1a575081155b610b8c5760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610db2565b5f805f610f67845f612349565b9250925092509193909250565b600d8181548110610f83575f80fd5b5f918252602090912001546001600160a01b0316905081565b6031546001600160a01b03161561100d576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610fdf9085908790600401613311565b5f604051808303815f87803b158015610ff6575f80fd5b505af1158015611008573d5f803e3d5ffd5b505050505b505050565b5f805f610f67846001612349565b5f611029611b4e565b611034866005611b9e565b6025546001600160a01b03161580159061105c57506025546001600160a01b03858116911614155b1561106957506001611267565b611075610af586611bec565b6015545f906001600160a01b0388811691161461110757611098610af588611bec565b6040516395dd919360e01b81526001600160a01b0385811660048301528816906395dd919390602401602060405180830381865afa1580156110dc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611100919061332b565b9050611176565b601554604051633c617c9160e11b81526001600160a01b038681166004830152909116906378c2f92290602401602060405180830381865afa15801561114f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611173919061332b565b90505b6001600160a01b0387165f908152602d602052604090205460ff16806111c057506001600160a01b038085165f908152603260209081526040808320938b168352929052205460ff165b156111de57808311156111d85760115b915050611267565b5f6111d0565b5f806111ee865f805f6001611f71565b9193509091505f905082601481111561120957611209613342565b1461122a5781601481111561122057611220613342565b9350505050611267565b805f03611238576003611220565b611252604051806020016040528060055481525084612381565b851115611260576011611220565b5f93505050505b95945050505050565b6031546001600160a01b031615610bfd576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906112b39086908890600401613311565b5f604051808303815f87803b1580156112ca575f80fd5b505af11580156112dc573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610bcf9085908890600401613311565b6031546001600160a01b031615610ace576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906113559085908990600401613311565b5f604051808303815f87803b15801561136c575f80fd5b505af115801561137e573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610aa09086908990600401613311565b60366020525f90815260409020805481906113ce90613356565b80601f01602080910402602001604051908101604052809291908181526020018280546113fa90613356565b80156114455780601f1061141c57610100808354040283529160200191611445565b820191905f5260205f20905b81548152906001019060200180831161142857829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f61146a611b4e565b611475856006611b9e565b5f611481868685612398565b90508015611490579050610b84565b6114998661203e565b6114a386866121ab565b610b7f86856121ab565b5f6114b6611b4e565b6114c1866004611b9e565b5f6114cb87611bec565b90506114d681611c0e565b6001600160a01b0384165f90815260028201602052604090205460ff166114fe5760136111d0565b6015546001600160a01b0387811691161461151f5761151f610af587611bec565b856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561155b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061157f919061338e565b6001600160a01b0316876001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115c4573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115e8919061338e565b6001600160a01b0316146115fd5760026111d0565b6116068761203e565b61161087856121ab565b61161a87866121ab565b5f979650505050505050565b5f61162f611b4e565b61163a846002611b9e565b611646610af585611bec565b6116508385612431565b6001600160a01b0384165f908152601f6020526040812054908190036116b15760405162461bcd60e51b815260206004820152601660248201527506d61726b657420626f72726f772063617020697320360541b6044820152606401610db2565b6116ba85611bec565b6001600160a01b0385165f908152600291909101602052604090205460ff1661176f57336001600160a01b0386161461172d5760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba103132903b2a37b5b2b760591b6044820152606401610db2565b5f61173886866124f4565b90505f81601481111561174d5761174d613342565b1461176d5780601481111561176457611764613342565b92505050610f07565b505b6004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa1580156117b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117dd919061332b565b5f036117ed57600d915050610f07565b5f611857866001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561182d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611851919061332b565b856125c7565b9050818111156118a95760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610db2565b5f806118b887895f895f611f71565b9193509091505f90508260148111156118d3576118d3613342565b146118f5578160148111156118ea576118ea613342565b945050505050610f07565b80156119025760046118ea565b5f60405180602001604052808a6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561194a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061196e919061332b565b9052905061197c8982611c56565b611987898983611ded565b5f9998505050505050505050565b6008602052815f5260405f2081815481106119ae575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f908152602960205260408120818360088111156119f3576119f3613342565b815260208101919091526040015f205460ff169392505050565b5f611a16611b4e565b611a21846001611b9e565b5f611a2d858585612398565b90508015611a3c579050610f07565b611a458561203e565b611a4f85856121ab565b5f95945050505050565b611a616125fc565b848381148015611a7057508082145b611aac5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610db2565b5f5b81811015610bf857611ae5888883818110611acb57611acb6133a9565b9050602002016020810190611ae09190612edf565b612646565b611b46888883818110611afa57611afa6133a9565b9050602002016020810190611b0f9190612edf565b878784818110611b2157611b216133a9565b90506020020135868685818110611b3a57611b3a6133a9565b90506020020135612694565b600101611aae565b60185462010000900460ff1615611b9c5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610db2565b565b611ba882826119c9565b15611be85760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610db2565b5050565b5f60095f611bfa5f85610cdb565b81526020019081526020015f209050919050565b805460ff16611c535760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610db2565b50565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611c8261280e565b83549091505f90611ca39063ffffffff80851691600160e01b900416612847565b90508015801590611cb357508215155b15611dc2575f611d22876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d1c919061332b565b87612880565b90505f611d2f838661289d565b90505f825f03611d4d5760405180602001604052805f815250611d57565b611d5782846128de565b604080516020810190915288546001600160e01b03168152909150611da090611d809083612921565b516040805180820190915260038152620c8c8d60ea1b602082015261294a565b6001600160e01b0316600160e01b63ffffffff87160217875550610cd3915050565b8015610cd357835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b601b546001600160a01b031615611e0657611e06612978565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b03909216908190559080158015611e6257506a0c097ce7bc90715b34b9f160241b8210155b15611e7857506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611e8e8585612847565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f91611ee791611ee1918a16906395dd919390602401602060405180830381865afa158015611cf8573d5f803e3d5ffd5b83612aea565b6001600160a01b0387165f90815260146020526040902054909150611f0c90826125c7565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e90611fb79030908f908f908f908f908f906004016133bd565b606060405180830381865afa158015611fd2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ff69190613418565b92509250925082601481111561200e5761200e613342565b9b919a5098509650505050505050565b5f8061202a8585612b11565b905061126761203882612b37565b846125c7565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161206a61280e565b83549091505f9061208b9063ffffffff80851691600160e01b900416612847565b9050801580159061209b57508215155b15612181575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156120dd573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612101919061332b565b90505f61210e838661289d565b90505f825f0361212c5760405180602001604052805f815250612136565b61213682846128de565b604080516020810190915288546001600160e01b0316815290915061215f90611d809083612921565b6001600160e01b0316600160e01b63ffffffff87160217875550610ace915050565b8015610ace57835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b601b546001600160a01b0316156121c4576121c4612978565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b0390921690819055908015801561222057506a0c097ce7bc90715b34b9f160241b8210155b1561223657506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061224c8585612847565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f916122c091908816906370a0823190602401602060405180830381865afa15801561229c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611ee1919061332b565b6001600160a01b0386165f908152601460205260409020549091506122e590826125c7565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f805f805f8061235c885f805f8b611f71565b92509250925082601481111561237457612374613342565b9891975095509350505050565b5f8061238d8484612b11565b9050610b8481612b37565b5f6123a5610af585611bec565b6123ae84611bec565b6001600160a01b0384165f908152600291909101602052604090205460ff166123d857505f610f07565b5f806123e78587865f80611f71565b9193509091505f905082601481111561240257612402613342565b146124195781601481111561176457611764613342565b8015612426576004611764565b5f9695505050505050565b6001600160a01b0382165f908152603560205260408120546001600160601b03169061245d8284610cdb565b5f81815260096020526040902060060154909150600160601b900460ff16612498576040516305b80c7960e41b815260040160405180910390fd5b6001600160601b038216158015906124cb57506001600160601b0382165f9081526036602052604090206002015460ff16155b15610bfd57604051632da4cc0560e01b81526001600160601b0383166004820152602401610db2565b5f612500836007611b9e565b5f61250a84611bec565b905061251581611c0e565b6001600160a01b0383165f90815260028201602052604090205460ff1615612540575f915050610cf6565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b5f610f078383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612b4e565b5f546001600160a01b03163314611b9c5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610db2565b6001600160a01b038116611c535760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610db2565b6126a0610af584611bec565b6001600160a01b0383165f908152602b6020526040902054821461271c576126c78361203e565b6001600160a01b0383165f818152602b602052604090819020849055517fa9ff26899e4982e7634afa9f70115dcfb61a17d6e8cdd91aa837671d0ff40ba6906127139085815260200190565b60405180910390a25b6001600160a01b0383165f908152602a6020526040902054811461100d575f6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612782573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127a6919061332b565b905290506127b48482611c56565b6001600160a01b0384165f818152602a602052604090819020849055517f0c62c1bc89ec4c40dccb4d21543e782c5ba43897c0075d108d8964181ea3c51b906128009085815260200190565b60405180910390a250505050565b5f6128424360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612b87565b905090565b5f610f078383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612bae565b5f610f0761289684670de0b6b3a764000061289d565b8351612bdc565b5f610f0783836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612c0e565b60408051602081019091525f81526040518060200160405280612918612912866a0c097ce7bc90715b34b9f160241b61289d565b85612bdc565b90529392505050565b60408051602081019091525f81526040518060200160405280612918855f0151855f01516125c7565b5f81600160e01b84106129705760405162461bcd60e51b8152600401610db29190613443565b509192915050565b601c5415806129885750601c5443105b1561298f57565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156129d9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906129fd919061332b565b9050805f03612a0a575050565b5f80612a1843601c54612847565b90505f612a27601a548361289d565b9050808410612a3857809250612a3c565b8392505b601d54831015612a4d575050505050565b43601c55601b54612a6b906001600160a01b03878116911685612c5e565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ab7575f80fd5b5f6a0c097ce7bc90715b34b9f160241b612b0784845f015161289d565b610f079190613469565b60408051602081019091525f81526040518060200160405280612918855f01518561289d565b80515f90610cf690670de0b6b3a764000090613469565b5f80612b5a8486613488565b90508285821015612b7e5760405162461bcd60e51b8152600401610db29190613443565b50949350505050565b5f8164010000000084106129705760405162461bcd60e51b8152600401610db29190613443565b5f8184841115612bd15760405162461bcd60e51b8152600401610db29190613443565b50610b84838561349b565b5f610f0783836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612cb0565b5f831580612c1a575082155b15612c2657505f610f07565b5f612c3184866134ae565b905083612c3e8683613469565b148390612b7e5760405162461bcd60e51b8152600401610db29190613443565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261100d908490612cdb565b5f8183612cd05760405162461bcd60e51b8152600401610db29190613443565b50610b848385613469565b5f612d2f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612dae9092919063ffffffff16565b905080515f1480612d4f575080806020019051810190612d4f91906134c5565b61100d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610db2565b6060610b8484845f85855f80866001600160a01b03168587604051612dd391906134e4565b5f6040518083038185875af1925050503d805f8114612e0d576040519150601f19603f3d011682016040523d82523d5f602084013e612e12565b606091505b5091509150612e2387838387612e2e565b979650505050505050565b60608315612e9c5782515f03612e95576001600160a01b0385163b612e955760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610db2565b5081610b84565b610b848383815115612eb15781518083602001fd5b8060405162461bcd60e51b8152600401610db29190613443565b6001600160a01b0381168114611c53575f80fd5b5f60208284031215612eef575f80fd5b8135610f0781612ecb565b5f8060408385031215612f0b575f80fd5b8235612f1681612ecb565b91506020830135612f2681612ecb565b809150509250929050565b5f805f805f60a08688031215612f45575f80fd5b8535612f5081612ecb565b94506020860135612f6081612ecb565b93506040860135612f7081612ecb565b94979396509394606081013594506080013592915050565b5f805f8060808587031215612f9b575f80fd5b8435612fa681612ecb565b93506020850135612fb681612ecb565b92506040850135612fc681612ecb565b9396929550929360600135925050565b5f805f8060808587031215612fe9575f80fd5b8435612ff481612ecb565b9350602085013561300481612ecb565b93969395505050506040820135916060013590565b5f805f805f8060c0878903121561302e575f80fd5b863561303981612ecb565b9550602087013561304981612ecb565b9450604087013561305981612ecb565b9350606087013561306981612ecb565b9598949750929560808101359460a0909101359350915050565b80356001600160601b0381168114613099575f80fd5b919050565b5f80604083850312156130af575f80fd5b612f1683613083565b5f805f606084860312156130ca575f80fd5b83356130d581612ecb565b925060208401356130e581612ecb565b929592945050506040919091013590565b5f60208284031215613106575f80fd5b5035919050565b5f805f805f60a08688031215613121575f80fd5b853561312c81612ecb565b9450602086013561313c81612ecb565b9350604086013561314c81612ecb565b9250606086013561315c81612ecb565b949793965091946080013592915050565b5f6020828403121561317d575f80fd5b610f0782613083565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6131c66060830186613186565b931515602083015250901515604090910152919050565b5f80604083850312156131ee575f80fd5b82356131f981612ecb565b946020939093013593505050565b5f8060408385031215613218575f80fd5b823561322381612ecb565b9150602083013560098110612f26575f80fd5b5f8083601f840112613246575f80fd5b50813567ffffffffffffffff81111561325d575f80fd5b6020830191508360208260051b8501011115613277575f80fd5b9250929050565b5f805f805f8060608789031215613293575f80fd5b863567ffffffffffffffff808211156132aa575f80fd5b6132b68a838b01613236565b909850965060208901359150808211156132ce575f80fd5b6132da8a838b01613236565b909650945060408901359150808211156132f2575f80fd5b506132ff89828a01613236565b979a9699509497509295939492505050565b6001600160a01b0392831681529116602082015260400190565b5f6020828403121561333b575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c9082168061336a57607f821691505b60208210810361338857634e487b7160e01b5f52602260045260245ffd5b50919050565b5f6020828403121561339e575f80fd5b8151610f0781612ecb565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c081016002831061340757634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f6060848603121561342a575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610f076020830184613186565b634e487b7160e01b5f52601160045260245ffd5b5f8261348357634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610cf657610cf6613455565b81810381811115610cf657610cf6613455565b8082028115828204841417610cf657610cf6613455565b5f602082840312156134d5575f80fd5b81518015158114610f07575f80fd5b5f82518060208501845e5f92019182525091905056fea26469706673582212207cd5f621d2b69e8b6c5d9a886845faa973f3a67a1195d459753ae549f728168064736f6c63430008190033", + "numDeployments": 11, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"VenusBorrowSpeedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSpeed\",\"type\":\"uint256\"}],\"name\":\"VenusSupplySpeedUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"supplySpeeds\",\"type\":\"uint256[]\"},{\"internalType\":\"uint256[]\",\"name\":\"borrowSpeeds\",\"type\":\"uint256[]\"}],\"name\":\"_setVenusSpeeds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"borrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getBorrowingPower\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenModify\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowAmount\",\"type\":\"uint256\"}],\"name\":\"getHypotheticalAccountLiquidity\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"liquidateBorrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"mintAmount\",\"type\":\"uint256\"}],\"name\":\"mintAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualMintAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"mintTokens\",\"type\":\"uint256\"}],\"name\":\"mintVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"redeemer\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"redeemAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"redeemTokens\",\"type\":\"uint256\"}],\"name\":\"redeemVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"repayBorrowAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"actualRepayAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowerIndex\",\"type\":\"uint256\"}],\"name\":\"repayBorrowVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"seizeVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferAllowed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"src\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"dst\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"transferTokens\",\"type\":\"uint256\"}],\"name\":\"transferVerify\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the hooks used while transferring the assets\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setVenusSpeeds(address[],uint256[],uint256[])\":{\"details\":\"Allows the contract admin to set XVS speed for a market\",\"params\":{\"borrowSpeeds\":\"New XVS speed for borrow\",\"supplySpeeds\":\"New XVS speed for supply\",\"vTokens\":\"The market whose XVS speed to update\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"borrowAllowed(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of underlying the account would borrow\",\"borrower\":\"The account which would borrow the asset\",\"vToken\":\"The market to verify the borrow against\"},\"returns\":{\"_0\":\"0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"borrowVerify(address,address,uint256)\":{\"params\":{\"borrowAmount\":\"The amount of the underlying asset requested to borrow\",\"borrower\":\"The address borrowing the underlying\",\"vToken\":\"Asset whose underlying is being borrowed\"}},\"getAccountLiquidity(address)\":{\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), account liquidity in excess of liquidation threshold requirements, account shortfall below liquidation threshold requirements)\"}},\"getBorrowingPower(address)\":{\"params\":{\"account\":\"The account get liquidity for\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), account liquidity in excess of collateral requirements, account shortfall below collateral requirements)\"}},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"params\":{\"account\":\"The account to determine liquidity for\",\"borrowAmount\":\"The amount of underlying to hypothetically borrow\",\"redeemTokens\":\"The number of tokens to hypothetically redeem\",\"vTokenModify\":\"The market to hypothetically redeem/borrow in\"},\"returns\":{\"_0\":\"(possible error code (semi-opaque), hypothetical account liquidity in excess of collateral requirements, hypothetical account shortfall below collateral requirements)\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"repayAmount\":\"The amount of underlying being repaid\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The amount of collateral token that will be seized\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"mintAllowed(address,address,uint256)\":{\"params\":{\"mintAmount\":\"The amount of underlying being supplied to the market in exchange for tokens\",\"minter\":\"The account which would get the minted tokens\",\"vToken\":\"The market to verify the mint against\"},\"returns\":{\"_0\":\"0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"mintVerify(address,address,uint256,uint256)\":{\"params\":{\"actualMintAmount\":\"The amount of the underlying asset being minted\",\"mintTokens\":\"The number of tokens being minted\",\"minter\":\"The address minting the tokens\",\"vToken\":\"Asset being minted\"}},\"redeemAllowed(address,address,uint256)\":{\"params\":{\"redeemTokens\":\"The number of vTokens to exchange for the underlying asset in the market\",\"redeemer\":\"The account which would redeem the tokens\",\"vToken\":\"The market to verify the redeem against\"},\"returns\":{\"_0\":\"0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"redeemVerify(address,address,uint256,uint256)\":{\"params\":{\"redeemAmount\":\"The amount of the underlying asset being redeemed\",\"redeemTokens\":\"The number of tokens being redeemed\",\"redeemer\":\"The address redeeming the tokens\",\"vToken\":\"Asset being redeemed\"}},\"repayBorrowAllowed(address,address,address,uint256)\":{\"params\":{\"borrower\":\"The account which borrowed the asset\",\"payer\":\"The account which would repay the asset\",\"repayAmount\":\"The amount of the underlying asset the account would repay\",\"vToken\":\"The market to verify the repay against\"},\"returns\":{\"_0\":\"0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"params\":{\"actualRepayAmount\":\"The amount of underlying being repaid\",\"borrower\":\"The address of the borrower\",\"payer\":\"The address repaying the borrow\",\"vToken\":\"Asset being repaid\"}},\"seizeAllowed(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"seizeVerify(address,address,address,address,uint256)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"liquidator\":\"The address repaying the borrow and seizing the collateral\",\"seizeTokens\":\"The number of collateral tokens to seize\",\"vTokenBorrowed\":\"Asset which was borrowed by the borrower\",\"vTokenCollateral\":\"Asset which was used as collateral and will be seized\"}},\"transferAllowed(address,address,address,uint256)\":{\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"The market to verify the transfer against\"},\"returns\":{\"_0\":\"0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\"}},\"transferVerify(address,address,address,uint256)\":{\"params\":{\"dst\":\"The account which receives the tokens\",\"src\":\"The account which sources the tokens\",\"transferTokens\":\"The number of vTokens to transfer\",\"vToken\":\"Asset being transferred\"}}},\"title\":\"PolicyFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedBorrowerVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a borrower\"},\"DistributedSupplierVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a supplier\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"VenusBorrowSpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new borrow-side XVS speed is calculated for a market\"},\"VenusSupplySpeedUpdated(address,uint256)\":{\"notice\":\"Emitted when a new supply-side XVS speed is calculated for a market\"}},\"kind\":\"user\",\"methods\":{\"_setVenusSpeeds(address[],uint256[],uint256[])\":{\"notice\":\"Set XVS speed for a single market\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to borrow the underlying asset of the given market\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"borrowVerify(address,address,uint256)\":{\"notice\":\"Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getAccountLiquidity(address)\":{\"notice\":\"Determine the current account liquidity wrt liquidation threshold requirements\"},\"getBorrowingPower(address)\":{\"notice\":\"Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\"},\"getHypotheticalAccountLiquidity(address,address,uint256,uint256)\":{\"notice\":\"Determine what the account liquidity would be if the given amounts were redeemed/borrowed\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"liquidateBorrowAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the liquidation should be allowed to occur\"},\"liquidateBorrowVerify(address,address,address,address,uint256,uint256)\":{\"notice\":\"Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to mint tokens in the given market\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"redeemAllowed(address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to redeem tokens in the given market\"},\"redeemVerify(address,address,uint256,uint256)\":{\"notice\":\"Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"repayBorrowAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to repay a borrow in the given market\"},\"repayBorrowVerify(address,address,address,uint256,uint256)\":{\"notice\":\"Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"seizeAllowed(address,address,address,address,uint256)\":{\"notice\":\"Checks if the seizing of assets should be allowed to occur\"},\"seizeVerify(address,address,address,address,uint256)\":{\"notice\":\"Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"transferAllowed(address,address,address,uint256)\":{\"notice\":\"Checks if the account should be allowed to transfer tokens in the given market\"},\"transferVerify(address,address,address,uint256)\":{\"notice\":\"Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains all the external pre-hook functions related to vToken\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/PolicyFacet.sol\":\"PolicyFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/PolicyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IPolicyFacet } from \\\"../interfaces/IPolicyFacet.sol\\\";\\n\\nimport { XVSRewardsHelper } from \\\"./XVSRewardsHelper.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title PolicyFacet\\n * @author Venus\\n * @dev This facet contains all the hooks used while transferring the assets\\n * @notice This facet contract contains all the external pre-hook functions related to vToken\\n */\\ncontract PolicyFacet is IPolicyFacet, XVSRewardsHelper {\\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\\n\\n /**\\n * @notice Checks if the account should be allowed to mint tokens in the given market\\n * @param vToken The market to verify the mint against\\n * @param minter The account which would get the minted tokens\\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.MINT);\\n ensureListed(getCorePoolMarket(vToken));\\n\\n uint256 supplyCap = supplyCaps[vToken];\\n require(supplyCap != 0, \\\"market supply cap is 0\\\");\\n\\n uint256 vTokenSupply = VToken(vToken).totalSupply();\\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\\n require(nextTotalSupply <= supplyCap, \\\"market supply cap reached\\\");\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, minter);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being minted\\n * @param minter The address minting the tokens\\n * @param actualMintAmount The amount of the underlying asset being minted\\n * @param mintTokens The number of tokens being minted\\n */\\n // solhint-disable-next-line no-unused-vars\\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(minter, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to redeem tokens in the given market\\n * @param vToken The market to verify the redeem against\\n * @param redeemer The account which would redeem the tokens\\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.REDEEM);\\n\\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\\n if (allowed != uint256(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, redeemer);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being redeemed\\n * @param redeemer The address redeeming the tokens\\n * @param redeemAmount The amount of the underlying asset being redeemed\\n * @param redeemTokens The number of tokens being redeemed\\n */\\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\\n require(redeemTokens != 0 || redeemAmount == 0, \\\"redeemTokens zero\\\");\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\\n * @param vToken The market to verify the borrow against\\n * @param borrower The account which would borrow the asset\\n * @param borrowAmount The amount of underlying the account would borrow\\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.BORROW);\\n ensureListed(getCorePoolMarket(vToken));\\n poolBorrowAllowed(borrower, vToken);\\n\\n uint256 borrowCap = borrowCaps[vToken];\\n require(borrowCap != 0, \\\"market borrow cap is 0\\\");\\n\\n if (!getCorePoolMarket(vToken).accountMembership[borrower]) {\\n // only vTokens may call borrowAllowed if borrower not in market\\n require(msg.sender == vToken, \\\"sender must be vToken\\\");\\n\\n // attempt to add borrower to the market\\n Error err = addToMarketInternal(VToken(vToken), borrower);\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n }\\n\\n (uint256 collateralPrice, uint256 debtPrice) = deviationBoundedOracle.getBoundedPricesView(vToken);\\n if (collateralPrice == 0 || debtPrice == 0) {\\n return uint256(Error.PRICE_ERROR);\\n }\\n\\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\\n require(nextTotalBorrows <= borrowCap, \\\"market borrow cap reached\\\");\\n\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n borrower,\\n VToken(vToken),\\n 0,\\n borrowAmount,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n updateVenusBorrowIndex(vToken, borrowIndex);\\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset whose underlying is being borrowed\\n * @param borrower The address borrowing the underlying\\n * @param borrowAmount The amount of the underlying asset requested to borrow\\n */\\n // solhint-disable-next-line no-unused-vars\\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to repay a borrow in the given market\\n * @param vToken The market to verify the repay against\\n * @param payer The account which would repay the asset\\n * @param borrower The account which borrowed the asset\\n * @param repayAmount The amount of the underlying asset the account would repay\\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function repayBorrowAllowed(\\n address vToken,\\n address payer, // solhint-disable-line no-unused-vars\\n address borrower,\\n uint256 repayAmount // solhint-disable-line no-unused-vars\\n ) external returns (uint256) {\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.REPAY);\\n ensureListed(getCorePoolMarket(vToken));\\n\\n // Keep the flywheel moving\\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\\n updateVenusBorrowIndex(vToken, borrowIndex);\\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being repaid\\n * @param payer The address repaying the borrow\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n */\\n function repayBorrowVerify(\\n address vToken,\\n address payer, // solhint-disable-line no-unused-vars\\n address borrower,\\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vToken);\\n }\\n }\\n\\n /**\\n * @notice Checks if the liquidation should be allowed to occur\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param repayAmount The amount of underlying being repaid\\n */\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount\\n ) external view returns (uint256) {\\n checkProtocolPauseState();\\n\\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\\n\\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\\n return uint256(Error.UNAUTHORIZED);\\n }\\n\\n ensureListed(getCorePoolMarket(vTokenCollateral));\\n uint256 borrowBalance;\\n if (address(vTokenBorrowed) != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\\n } else {\\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\\n }\\n\\n if (isForcedLiquidationEnabled[vTokenBorrowed] || isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed]) {\\n if (repayAmount > borrowBalance) {\\n return uint(Error.TOO_MUCH_REPAY);\\n }\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* The borrower must have shortfall in order to be liquidatable */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\\n borrower,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_LIQUIDATION_THRESHOLD\\n );\\n\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall == 0) {\\n return uint256(Error.INSUFFICIENT_SHORTFALL);\\n }\\n\\n // The liquidator may not repay more than what is allowed by the closeFactor\\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\\n return uint256(Error.TOO_MUCH_REPAY);\\n }\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param actualRepayAmount The amount of underlying being repaid\\n * @param seizeTokens The amount of collateral token that will be seized\\n */\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral, // solhint-disable-line no-unused-vars\\n address liquidator,\\n address borrower,\\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\\n }\\n }\\n\\n /**\\n * @notice Checks if the seizing of assets should be allowed to occur\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\\n\\n Market storage market = getCorePoolMarket(vTokenCollateral);\\n\\n // We've added VAIController as a borrowed token list check for seize\\n ensureListed(market);\\n\\n if (!market.accountMembership[borrower]) {\\n return uint256(Error.MARKET_NOT_COLLATERAL);\\n }\\n\\n if (address(vTokenBorrowed) != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n\\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\\n return uint256(Error.COMPTROLLER_MISMATCH);\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vTokenCollateral);\\n distributeSupplierVenus(vTokenCollateral, borrower);\\n distributeSupplierVenus(vTokenCollateral, liquidator);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vTokenCollateral Asset which was used as collateral and will be seized\\n * @param vTokenBorrowed Asset which was borrowed by the borrower\\n * @param liquidator The address repaying the borrow and seizing the collateral\\n * @param borrower The address of the borrower\\n * @param seizeTokens The number of collateral tokens to seize\\n */\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens // solhint-disable-line no-unused-vars\\n ) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\\n }\\n }\\n\\n /**\\n * @notice Checks if the account should be allowed to transfer tokens in the given market\\n * @param vToken The market to verify the transfer against\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\\n */\\n function transferAllowed(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external returns (uint256) {\\n // Pausing is a very serious situation - we revert to sound the alarms\\n checkProtocolPauseState();\\n checkActionPauseState(vToken, Action.TRANSFER);\\n\\n // Currently the only consideration is whether or not\\n // the src is allowed to redeem this many tokens\\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\\n if (allowed != uint256(Error.NO_ERROR)) {\\n return allowed;\\n }\\n\\n // Keep the flywheel moving\\n updateVenusSupplyIndex(vToken);\\n distributeSupplierVenus(vToken, src);\\n distributeSupplierVenus(vToken, dst);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\\n * @param vToken Asset being transferred\\n * @param src The account which sources the tokens\\n * @param dst The account which receives the tokens\\n * @param transferTokens The number of vTokens to transfer\\n */\\n // solhint-disable-next-line no-unused-vars\\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\\n if (address(prime) != address(0)) {\\n prime.accrueInterestAndUpdateScore(src, vToken);\\n prime.accrueInterestAndUpdateScore(dst, vToken);\\n }\\n }\\n\\n /**\\n * @notice Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\\n * @param account The account get liquidity for\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n return (uint256(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt liquidation threshold requirements\\n * @param account The account get liquidity for\\n * @return (possible error code (semi-opaque),\\n account liquidity in excess of liquidation threshold requirements,\\n * account shortfall below liquidation threshold requirements)\\n */\\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_LIQUIDATION_THRESHOLD\\n );\\n return (uint256(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @return (possible error code (semi-opaque),\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\\n account,\\n VToken(vTokenModify),\\n redeemTokens,\\n borrowAmount,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n return (uint256(err), liquidity, shortfall);\\n }\\n\\n // setter functionality\\n /**\\n * @notice Set XVS speed for a single market\\n * @dev Allows the contract admin to set XVS speed for a market\\n * @param vTokens The market whose XVS speed to update\\n * @param supplySpeeds New XVS speed for supply\\n * @param borrowSpeeds New XVS speed for borrow\\n */\\n function _setVenusSpeeds(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplySpeeds,\\n uint256[] calldata borrowSpeeds\\n ) external {\\n ensureAdmin();\\n\\n uint256 numTokens = vTokens.length;\\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numTokens; ++i) {\\n ensureNonzeroAddress(address(vTokens[i]));\\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\\n }\\n }\\n\\n /**\\n * @dev Internal function to set XVS speed for a single market\\n * @param vToken The market whose XVS speed to update\\n * @param supplySpeed New XVS speed for supply\\n * @param borrowSpeed New XVS speed for borrow\\n * @custom:event VenusSupplySpeedUpdated Emitted after the venus supply speed for a market is updated\\n * @custom:event VenusBorrowSpeedUpdated Emitted after the venus borrow speed for a market is updated\\n */\\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\\n ensureListed(getCorePoolMarket(address(vToken)));\\n\\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\\n // Supply speed updated so let's update supply state to ensure that\\n // 1. XVS accrued properly for the old speed, and\\n // 2. XVS accrued at the new speed starts after this block.\\n\\n updateVenusSupplyIndex(address(vToken));\\n // Update speed and emit event\\n venusSupplySpeeds[address(vToken)] = supplySpeed;\\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\\n }\\n\\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\\n // Borrow speed updated so let's update borrow state to ensure that\\n // 1. XVS accrued properly for the old speed, and\\n // 2. XVS accrued at the new speed starts after this block.\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n updateVenusBorrowIndex(address(vToken), borrowIndex);\\n\\n // Update speed and emit event\\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\\n }\\n }\\n\\n /**\\n * @dev Checks if vToken borrowing is allowed in the account's entered pool\\n * Reverts if borrowing is not permitted\\n * @param account The address of the account whose borrow permission is being checked\\n * @param vToken The vToken market to check borrowing status for\\n * @custom:error BorrowNotAllowedInPool Reverts if borrowing is not allowed in the account's entered pool\\n * @custom:error InactivePool Reverts if borrowing in an inactive pool.\\n */\\n function poolBorrowAllowed(address account, address vToken) internal view {\\n uint96 userPool = userPoolId[account];\\n PoolMarketId index = getPoolMarketIndex(userPool, vToken);\\n if (!_poolMarkets[index].isBorrowAllowed) {\\n revert BorrowNotAllowedInPool();\\n }\\n if (userPool != corePoolId && !pools[userPool].isActive) {\\n revert InactivePool(userPool);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x3d9e8e3929dd3766ce852b5fafd553a03bf086071987bc8501f474cd575d757f\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\n\\n/**\\n * @title XVSRewardsHelper\\n * @author Venus\\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\\n */\\ncontract XVSRewardsHelper is FacetBase {\\n /// @notice Emitted when XVS is distributed to a borrower\\n event DistributedBorrowerVenus(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 venusDelta,\\n uint256 venusBorrowIndex\\n );\\n\\n /// @notice Emitted when XVS is distributed to a supplier\\n event DistributedSupplierVenus(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 venusDelta,\\n uint256 venusSupplyIndex\\n );\\n\\n /**\\n * @notice Accrue XVS to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n */\\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\\n if (deltaBlocks != 0 && borrowSpeed != 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \\\"224\\\");\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n borrowState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Accrue XVS to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n */\\n function updateVenusSupplyIndex(address vToken) internal {\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n uint256 supplySpeed = venusSupplySpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\\n if (deltaBlocks != 0 && supplySpeed != 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \\\"224\\\");\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n supplyState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute XVS to\\n */\\n function distributeSupplierVenus(address vToken, address supplier) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 supplyIndex = venusSupplyState[vToken].index;\\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\\n // Update supplier's index to the current index since we are distributing accrued XVS\\n venusSupplierIndex[vToken][supplier] = supplyIndex;\\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n // Multiply of supplierTokens and supplierDelta\\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\\n // Addition of supplierAccrued and supplierDelta\\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute XVS to\\n */\\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 borrowIndex = venusBorrowState[vToken].index;\\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\\n // Update borrowers's index to the current index since we are distributing accrued XVS\\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0xf356db714f7aada286380ee5092b0a3e3163428943cfb5561ded76597e1c0c15\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IPolicyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\n\\ninterface IPolicyFacet {\\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\\n\\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\\n\\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\\n\\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint256 repayAmount\\n ) external returns (uint256);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint256 repayAmount,\\n uint256 borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount\\n ) external view returns (uint256);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n uint256 seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external returns (uint256);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint256 seizeTokens\\n ) external;\\n\\n function transferAllowed(\\n address vToken,\\n address src,\\n address dst,\\n uint256 transferTokens\\n ) external returns (uint256);\\n\\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\\n\\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\\n\\n function getHypotheticalAccountLiquidity(\\n address account,\\n address vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount\\n ) external view returns (uint256, uint256, uint256);\\n\\n function _setVenusSpeeds(\\n VToken[] calldata vTokens,\\n uint256[] calldata supplySpeeds,\\n uint256[] calldata borrowSpeeds\\n ) external;\\n\\n function getBorrowingPower(\\n address account\\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall);\\n}\\n\",\"keccak256\":\"0x6fd69f4b22548e9288f7c025d501966ae4f83132693a8e33f1e35ed55151d111\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b506136f58061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106103eb575f3560e01c80637fb8e8cd1161020b578063c7ee005e1161011f578063e0f6123d116100b4578063eabe7d9111610084578063eabe7d9114610a12578063ead1a8a014610a25578063f445d70314610a38578063f851a44014610a65578063fa6331d814610a77575f80fd5b8063e0f6123d1461099d578063e37d4b79146109bf578063e85a2960146109f6578063e875544614610a09575f80fd5b8063d7c46d2d116100ef578063d7c46d2d1461094c578063da3d454c14610964578063dce1544914610977578063dcfbc0c71461098a575f80fd5b8063c7ee005e1461090c578063d02f73511461091f578063d3270f9914610932578063d463654c14610945575f80fd5b8063b2eafc39116101a0578063bdcdc25811610170578063bdcdc2581461089f578063bec04f72146108b2578063bf32442d146108bb578063c5b4db55146108cc578063c5f956af146108f9575f80fd5b8063b2eafc39146107ff578063b8324c7c14610812578063bb82aa5e1461086d578063bbb8864a14610880575f80fd5b806394b2294b116101db57806394b2294b146107ae57806396c99064146107b75780639bb27d62146107d9578063a657e579146107ec575f80fd5b80637fb8e8cd1461074d5780638a7dc1651461075a5780638c1ac18a146107795780639254f5e51461079b575f80fd5b80634d99c776116103025780635ec88c7911610297578063719f701b11610267578063719f701b146106cc57806373769099146106d557806376551383146107155780637d172bd5146107275780637dc0d1d01461073a575f80fd5b80635ec88c79146106805780635fc7e71e146106935780636a56947e146106a65780636d35bf91146106b9575f80fd5b8063528a174c116102d2578063528a174c1461062857806352d84d1e1461063b5780635c7786051461064e5780635dd3fc9d14610661575f80fd5b80634d99c776146105c15780634e79238f146105d45780634ef4c3e11461060257806351dff98914610615575f80fd5b806324a3d6221161038357806341a18d2c1161035357806341a18d2c1461053f57806341c728b914610569578063425fad581461057c57806347ef3b3b1461058f5780634a584432146105a2575f80fd5b806324a3d622146104ed57806326782247146105005780632bc7e29e146105135780634088c73e14610532575f80fd5b806310b98338116103be57806310b983381461045d5780631ededc911461049a57806321af4569146104af57806324008a62146104da575f80fd5b806302c3bcbb146103ef57806304ef9d581461042157806308e0225c1461042a5780630db4b4e514610454575b5f80fd5b61040e6103fd366004613082565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61040e60225481565b61040e61043836600461309d565b601360209081525f928352604080842090915290825290205481565b61040e601d5481565b61048a61046b36600461309d565b602c60209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610418565b6104ad6104a83660046130d4565b610a80565b005b601e546104c2906001600160a01b031681565b6040516001600160a01b039091168152602001610418565b61040e6104e836600461312b565b610af8565b600a546104c2906001600160a01b031681565b6001546104c2906001600160a01b031681565b61040e610521366004613082565b60166020525f908152604090205481565b60185461048a9060ff1681565b61040e61054d36600461309d565b601260209081525f928352604080842090915290825290205481565b6104ad610577366004613179565b610baf565b60185461048a9062010000900460ff1681565b6104ad61059d3660046131bc565b610c26565b61040e6105b0366004613082565b601f6020525f908152604090205481565b61040e6105cf366004613241565b610cfe565b6105e76105e2366004613179565b610d1f565b60408051938452602084019290925290820152606001610418565b61040e61061036600461325b565b610d59565b6104ad610623366004613179565b610f31565b6105e7610636366004613082565b610f7d565b6104c2610649366004613299565b610fb4565b6104ad61065c36600461325b565b610fdc565b61040e61066f366004613082565b602b6020525f908152604090205481565b6105e761068e366004613082565b611052565b61040e6106a13660046132b0565b611066565b6104ad6106b436600461312b565b6112b6565b6104ad6106c73660046132b0565b611358565b61040e601c5481565b6106fd6106e3366004613082565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610418565b60185461048a90610100900460ff1681565b601b546104c2906001600160a01b031681565b6004546104c2906001600160a01b031681565b60395461048a9060ff1681565b61040e610768366004613082565b60146020525f908152604090205481565b61048a610787366004613082565b602d6020525f908152604090205460ff1681565b6015546104c2906001600160a01b031681565b61040e60075481565b6107ca6107c5366004613310565b6113fa565b60405161041893929190613357565b6025546104c2906001600160a01b031681565b6037546106fd906001600160601b031681565b6020546104c2906001600160a01b031681565b610849610820366004613082565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610418565b6002546104c2906001600160a01b031681565b61040e61088e366004613082565b602a6020525f908152604090205481565b61040e6108ad36600461312b565b6114a7565b61040e60175481565b6033546001600160a01b03166104c2565b6108e16a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b039091168152602001610418565b6021546104c2906001600160a01b031681565b6031546104c2906001600160a01b031681565b61040e61092d3660046132b0565b6114f3565b6026546104c2906001600160a01b031681565b6106fd5f81565b6039546104c29061010090046001600160a01b031681565b61040e61097236600461325b565b61166c565b6104c2610985366004613380565b6119f7565b6003546104c2906001600160a01b031681565b61048a6109ab366004613082565b60386020525f908152604090205460ff1681565b6108496109cd366004613082565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61048a610a043660046133aa565b611a2b565b61040e60055481565b61040e610a2036600461325b565b611a6f565b6104ad610a33366004613421565b611abb565b61048a610a4636600461309d565b603260209081525f928352604080842090915290825290205460ff1681565b5f546104c2906001600160a01b031681565b61040e601a5481565b6031546001600160a01b031615610af1576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610ac390869089906004016134b4565b5f604051808303815f87803b158015610ada575f80fd5b505af1158015610aec573d5f803e3d5ffd5b505050505b5050505050565b5f610b01611bb0565b610b0c856003611c00565b610b1d610b1886611c4e565b611c70565b5f6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b8991906134ce565b90529050610b978682611cb8565b610ba2868583611e4f565b5f9150505b949350505050565b6031546001600160a01b031615610c20576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610bf290869088906004016134b4565b5f604051808303815f87803b158015610c09575f80fd5b505af1158015610c1b573d5f803e3d5ffd5b505050505b50505050565b6031546001600160a01b031615610cf6576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610c699086908a906004016134b4565b5f604051808303815f87803b158015610c80575f80fd5b505af1158015610c92573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610cc89087908a906004016134b4565b5f604051808303815f87803b158015610cdf575f80fd5b505af1158015610cf1573d5f803e3d5ffd5b505050505b505050505050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b5f805f805f80610d328a8a8a8a5f611fd3565b925092509250826014811115610d4a57610d4a6134e5565b9a919950975095505050505050565b5f610d62611bb0565b610d6c845f611c00565b610d78610b1885611c4e565b6001600160a01b0384165f9081526027602052604081205490819003610dde5760405162461bcd60e51b815260206004820152601660248201527506d61726b657420737570706c792063617020697320360541b60448201526064015b60405180910390fd5b5f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3f91906134ce565b90505f6040518060200160405280886001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ead91906134ce565b905290505f610ebd828488612080565b905083811115610f0f5760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420737570706c79206361702072656163686564000000000000006044820152606401610dd5565b610f18886120a0565b610f22888861220d565b5f9450505050505b9392505050565b80151580610f3d575081155b610baf5760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610dd5565b5f805f805f80610f90875f805f80611fd3565b925092509250826014811115610fa857610fa86134e5565b97919650945092505050565b600d8181548110610fc3575f80fd5b5f918252602090912001546001600160a01b0316905081565b6031546001600160a01b03161561104d576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d169061101f90859087906004016134b4565b5f604051808303815f87803b158015611036575f80fd5b505af1158015611048573d5f803e3d5ffd5b505050505b505050565b5f805f805f80610f90875f805f6001611fd3565b5f61106f611bb0565b61107a866005611c00565b6025546001600160a01b0316158015906110a257506025546001600160a01b03858116911614155b156110af575060016112ad565b6110bb610b1886611c4e565b6015545f906001600160a01b0388811691161461114d576110de610b1888611c4e565b6040516395dd919360e01b81526001600160a01b0385811660048301528816906395dd919390602401602060405180830381865afa158015611122573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061114691906134ce565b90506111bc565b601554604051633c617c9160e11b81526001600160a01b038681166004830152909116906378c2f92290602401602060405180830381865afa158015611195573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111b991906134ce565b90505b6001600160a01b0387165f908152602d602052604090205460ff168061120657506001600160a01b038085165f908152603260209081526040808320938b168352929052205460ff165b15611224578083111561121e5760115b9150506112ad565b5f611216565b5f80611234865f805f6001611fd3565b9193509091505f905082601481111561124f5761124f6134e5565b1461127057816014811115611266576112666134e5565b93505050506112ad565b805f0361127e576003611266565b6112986040518060200160405280600554815250846123ab565b8511156112a6576011611266565b5f93505050505b95945050505050565b6031546001600160a01b031615610c20576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906112f990869088906004016134b4565b5f604051808303815f87803b158015611310575f80fd5b505af1158015611322573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610bf290859088906004016134b4565b6031546001600160a01b031615610af1576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d169061139b90859089906004016134b4565b5f604051808303815f87803b1580156113b2575f80fd5b505af11580156113c4573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610ac390869089906004016134b4565b60366020525f9081526040902080548190611414906134f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611440906134f9565b801561148b5780601f106114625761010080835404028352916020019161148b565b820191905f5260205f20905b81548152906001019060200180831161146e57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6114b0611bb0565b6114bb856006611c00565b5f6114c78686856123c2565b905080156114d6579050610ba7565b6114df866120a0565b6114e9868661220d565b610ba2868561220d565b5f6114fc611bb0565b611507866004611c00565b5f61151187611c4e565b905061151c81611c70565b6001600160a01b0384165f90815260028201602052604090205460ff16611544576013611216565b6015546001600160a01b0387811691161461156557611565610b1887611c4e565b856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115c59190613531565b6001600160a01b0316876001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561160a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061162e9190613531565b6001600160a01b031614611643576002611216565b61164c876120a0565b611656878561220d565b611660878661220d565b5f979650505050505050565b5f611675611bb0565b611680846002611c00565b61168c610b1885611c4e565b611696838561245b565b6001600160a01b0384165f908152601f6020526040812054908190036116f75760405162461bcd60e51b815260206004820152601660248201527506d61726b657420626f72726f772063617020697320360541b6044820152606401610dd5565b61170085611c4e565b6001600160a01b0385165f908152600291909101602052604090205460ff166117b557336001600160a01b038616146117735760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba103132903b2a37b5b2b760591b6044820152606401610dd5565b5f61177e868661251e565b90505f816014811115611793576117936134e5565b146117b3578060148111156117aa576117aa6134e5565b92505050610f2a565b505b6039546040516388142b6b60e01b81526001600160a01b0387811660048301525f928392610100909104909116906388142b6b906024016040805180830381865afa158015611806573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061182a919061354c565b91509150815f148061183a575080155b1561184b57600d9350505050610f2a565b5f6118b5886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561188b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118af91906134ce565b876125f1565b9050838111156119075760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610dd5565b5f80611916898b5f8b5f612626565b9193509091505f9050826014811115611931576119316134e5565b1461195557816014811115611948576119486134e5565b9650505050505050610f2a565b8015611962576004611948565b5f60405180602001604052808c6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ce91906134ce565b905290506119dc8b82611cb8565b6119e78b8b83611e4f565b5f9b9a5050505050505050505050565b6008602052815f5260405f208181548110611a10575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611a5557611a556134e5565b815260208101919091526040015f205460ff169392505050565b5f611a78611bb0565b611a83846001611c00565b5f611a8f8585856123c2565b90508015611a9e579050610f2a565b611aa7856120a0565b611ab1858561220d565b5f95945050505050565b611ac3612688565b848381148015611ad257508082145b611b0e5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610dd5565b5f5b81811015610c1b57611b47888883818110611b2d57611b2d61356e565b9050602002016020810190611b429190613082565b6126d2565b611ba8888883818110611b5c57611b5c61356e565b9050602002016020810190611b719190613082565b878784818110611b8357611b8361356e565b90506020020135868685818110611b9c57611b9c61356e565b90506020020135612720565b600101611b10565b60185462010000900460ff1615611bfe5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610dd5565b565b611c0a8282611a2b565b15611c4a5760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610dd5565b5050565b5f60095f611c5c5f85610cfe565b81526020019081526020015f209050919050565b805460ff16611cb55760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610dd5565b50565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611ce461289a565b83549091505f90611d059063ffffffff80851691600160e01b9004166128d3565b90508015801590611d1557508215155b15611e24575f611d84876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d7e91906134ce565b8761290c565b90505f611d918386612929565b90505f825f03611daf5760405180602001604052805f815250611db9565b611db9828461296a565b604080516020810190915288546001600160e01b03168152909150611e0290611de290836129ad565b516040805180820190915260038152620c8c8d60ea1b60208201526129d6565b6001600160e01b0316600160e01b63ffffffff87160217875550610cf6915050565b8015610cf657835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b601b546001600160a01b031615611e6857611e68612a04565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b03909216908190559080158015611ec457506a0c097ce7bc90715b34b9f160241b8210155b15611eda57506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611ef085856128d3565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f91611f4991611f43918a16906395dd919390602401602060405180830381865afa158015611d5a573d5f803e3d5ffd5b83612b76565b6001600160a01b0387165f90815260146020526040902054909150611f6e90826125f1565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e906120199030908f908f908f908f908f90600401613582565b606060405180830381865afa158015612034573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061205891906135dd565b925092509250826014811115612070576120706134e5565b9b919a5098509650505050505050565b5f8061208c8585612b9d565b90506112ad61209a82612bc3565b846125f1565b6001600160a01b0381165f908152601060209081526040808320602b90925282205490916120cc61289a565b83549091505f906120ed9063ffffffff80851691600160e01b9004166128d3565b905080158015906120fd57508215155b156121e3575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216391906134ce565b90505f6121708386612929565b90505f825f0361218e5760405180602001604052805f815250612198565b612198828461296a565b604080516020810190915288546001600160e01b031681529091506121c190611de290836129ad565b6001600160e01b0316600160e01b63ffffffff87160217875550610af1915050565b8015610af157835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b601b546001600160a01b03161561222657612226612a04565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b0390921690819055908015801561228257506a0c097ce7bc90715b34b9f160241b8210155b1561229857506a0c097ce7bc90715b34b9f160241b5b5f60405180602001604052806122ae85856128d3565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f9161232291908816906370a0823190602401602060405180830381865afa1580156122fe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4391906134ce565b6001600160a01b0386165f9081526014602052604090205490915061234790826125f1565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f806123b78484612b9d565b9050610ba781612bc3565b5f6123cf610b1885611c4e565b6123d884611c4e565b6001600160a01b0384165f908152600291909101602052604090205460ff1661240257505f610f2a565b5f806124118587865f80612626565b9193509091505f905082601481111561242c5761242c6134e5565b14612443578160148111156117aa576117aa6134e5565b80156124505760046117aa565b5f9695505050505050565b6001600160a01b0382165f908152603560205260408120546001600160601b0316906124878284610cfe565b5f81815260096020526040902060060154909150600160601b900460ff166124c2576040516305b80c7960e41b815260040160405180910390fd5b6001600160601b038216158015906124f557506001600160601b0382165f9081526036602052604090206002015460ff16155b15610c2057604051632da4cc0560e01b81526001600160601b0383166004820152602401610dd5565b5f61252a836007611c00565b5f61253484611c4e565b905061253f81611c70565b6001600160a01b0383165f90815260028201602052604090205460ff161561256a575f915050610d19565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b5f610f2a8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612bda565b5f80808084600181111561263c5761263c6134e5565b0361264a5761264a88612c13565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e906120199030908f908f908f908f908f90600401613582565b5f546001600160a01b03163314611bfe5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610dd5565b6001600160a01b038116611cb55760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610dd5565b61272c610b1884611c4e565b6001600160a01b0383165f908152602b602052604090205482146127a857612753836120a0565b6001600160a01b0383165f818152602b602052604090819020849055517fa9ff26899e4982e7634afa9f70115dcfb61a17d6e8cdd91aa837671d0ff40ba69061279f9085815260200190565b60405180910390a25b6001600160a01b0383165f908152602a6020526040902054811461104d575f6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561280e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061283291906134ce565b905290506128408482611cb8565b6001600160a01b0384165f818152602a602052604090819020849055517f0c62c1bc89ec4c40dccb4d21543e782c5ba43897c0075d108d8964181ea3c51b9061288c9085815260200190565b60405180910390a250505050565b5f6128ce4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612d2a565b905090565b5f610f2a8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612d51565b5f610f2a61292284670de0b6b3a7640000612929565b8351612d7f565b5f610f2a83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612db1565b60408051602081019091525f815260405180602001604052806129a461299e866a0c097ce7bc90715b34b9f160241b612929565b85612d7f565b90529392505050565b60408051602081019091525f815260405180602001604052806129a4855f0151855f01516125f1565b5f81600160e01b84106129fc5760405162461bcd60e51b8152600401610dd59190613608565b509192915050565b601c541580612a145750601c5443105b15612a1b57565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015612a65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a8991906134ce565b9050805f03612a96575050565b5f80612aa443601c546128d3565b90505f612ab3601a5483612929565b9050808410612ac457809250612ac8565b8392505b601d54831015612ad9575050505050565b43601c55601b54612af7906001600160a01b03878116911685612e01565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ada575f80fd5b5f6a0c097ce7bc90715b34b9f160241b612b9384845f0151612929565b610f2a919061362e565b60408051602081019091525f815260405180602001604052806129a4855f015185612929565b80515f90610d1990670de0b6b3a76400009061362e565b5f80612be6848661364d565b90508285821015612c0a5760405162461bcd60e51b8152600401610dd59190613608565b50949350505050565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015612c8957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612c6b575b505083519394505f925050505b81811015610af157836001600160a01b031663a9c3cab1848381518110612cbf57612cbf61356e565b60200260200101516040518263ffffffff1660e01b8152600401612cf291906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015612d09575f80fd5b505af1158015612d1b573d5f803e3d5ffd5b50505050806001019050612c96565b5f8164010000000084106129fc5760405162461bcd60e51b8152600401610dd59190613608565b5f8184841115612d745760405162461bcd60e51b8152600401610dd59190613608565b50610ba78385613660565b5f610f2a83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612e53565b5f831580612dbd575082155b15612dc957505f610f2a565b5f612dd48486613673565b905083612de1868361362e565b148390612c0a5760405162461bcd60e51b8152600401610dd59190613608565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261104d908490612e7e565b5f8183612e735760405162461bcd60e51b8152600401610dd59190613608565b50610ba7838561362e565b5f612ed2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f519092919063ffffffff16565b905080515f1480612ef2575080806020019051810190612ef2919061368a565b61104d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610dd5565b6060610ba784845f85855f80866001600160a01b03168587604051612f7691906136a9565b5f6040518083038185875af1925050503d805f8114612fb0576040519150601f19603f3d011682016040523d82523d5f602084013e612fb5565b606091505b5091509150612fc687838387612fd1565b979650505050505050565b6060831561303f5782515f03613038576001600160a01b0385163b6130385760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dd5565b5081610ba7565b610ba783838151156130545781518083602001fd5b8060405162461bcd60e51b8152600401610dd59190613608565b6001600160a01b0381168114611cb5575f80fd5b5f60208284031215613092575f80fd5b8135610f2a8161306e565b5f80604083850312156130ae575f80fd5b82356130b98161306e565b915060208301356130c98161306e565b809150509250929050565b5f805f805f60a086880312156130e8575f80fd5b85356130f38161306e565b945060208601356131038161306e565b935060408601356131138161306e565b94979396509394606081013594506080013592915050565b5f805f806080858703121561313e575f80fd5b84356131498161306e565b935060208501356131598161306e565b925060408501356131698161306e565b9396929550929360600135925050565b5f805f806080858703121561318c575f80fd5b84356131978161306e565b935060208501356131a78161306e565b93969395505050506040820135916060013590565b5f805f805f8060c087890312156131d1575f80fd5b86356131dc8161306e565b955060208701356131ec8161306e565b945060408701356131fc8161306e565b9350606087013561320c8161306e565b9598949750929560808101359460a0909101359350915050565b80356001600160601b038116811461323c575f80fd5b919050565b5f8060408385031215613252575f80fd5b6130b983613226565b5f805f6060848603121561326d575f80fd5b83356132788161306e565b925060208401356132888161306e565b929592945050506040919091013590565b5f602082840312156132a9575f80fd5b5035919050565b5f805f805f60a086880312156132c4575f80fd5b85356132cf8161306e565b945060208601356132df8161306e565b935060408601356132ef8161306e565b925060608601356132ff8161306e565b949793965091946080013592915050565b5f60208284031215613320575f80fd5b610f2a82613226565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6133696060830186613329565b931515602083015250901515604090910152919050565b5f8060408385031215613391575f80fd5b823561339c8161306e565b946020939093013593505050565b5f80604083850312156133bb575f80fd5b82356133c68161306e565b91506020830135600981106130c9575f80fd5b5f8083601f8401126133e9575f80fd5b50813567ffffffffffffffff811115613400575f80fd5b6020830191508360208260051b850101111561341a575f80fd5b9250929050565b5f805f805f8060608789031215613436575f80fd5b863567ffffffffffffffff8082111561344d575f80fd5b6134598a838b016133d9565b90985096506020890135915080821115613471575f80fd5b61347d8a838b016133d9565b90965094506040890135915080821115613495575f80fd5b506134a289828a016133d9565b979a9699509497509295939492505050565b6001600160a01b0392831681529116602082015260400190565b5f602082840312156134de575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c9082168061350d57607f821691505b60208210810361352b57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613541575f80fd5b8151610f2a8161306e565b5f806040838503121561355d575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101600283106135cc57634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f606084860312156135ef575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610f2a6020830184613329565b634e487b7160e01b5f52601160045260245ffd5b5f8261364857634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610d1957610d1961361a565b81810381811115610d1957610d1961361a565b8082028115828204841417610d1957610d1961361a565b5f6020828403121561369a575f80fd5b81518015158114610f2a575f80fd5b5f82518060208501845e5f92019182525091905056fea2646970667358221220a577d175a4a6a3d87eb45e30d1f3b89394de97350923b50e6a0238ad20ddede864736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106103eb575f3560e01c80637fb8e8cd1161020b578063c7ee005e1161011f578063e0f6123d116100b4578063eabe7d9111610084578063eabe7d9114610a12578063ead1a8a014610a25578063f445d70314610a38578063f851a44014610a65578063fa6331d814610a77575f80fd5b8063e0f6123d1461099d578063e37d4b79146109bf578063e85a2960146109f6578063e875544614610a09575f80fd5b8063d7c46d2d116100ef578063d7c46d2d1461094c578063da3d454c14610964578063dce1544914610977578063dcfbc0c71461098a575f80fd5b8063c7ee005e1461090c578063d02f73511461091f578063d3270f9914610932578063d463654c14610945575f80fd5b8063b2eafc39116101a0578063bdcdc25811610170578063bdcdc2581461089f578063bec04f72146108b2578063bf32442d146108bb578063c5b4db55146108cc578063c5f956af146108f9575f80fd5b8063b2eafc39146107ff578063b8324c7c14610812578063bb82aa5e1461086d578063bbb8864a14610880575f80fd5b806394b2294b116101db57806394b2294b146107ae57806396c99064146107b75780639bb27d62146107d9578063a657e579146107ec575f80fd5b80637fb8e8cd1461074d5780638a7dc1651461075a5780638c1ac18a146107795780639254f5e51461079b575f80fd5b80634d99c776116103025780635ec88c7911610297578063719f701b11610267578063719f701b146106cc57806373769099146106d557806376551383146107155780637d172bd5146107275780637dc0d1d01461073a575f80fd5b80635ec88c79146106805780635fc7e71e146106935780636a56947e146106a65780636d35bf91146106b9575f80fd5b8063528a174c116102d2578063528a174c1461062857806352d84d1e1461063b5780635c7786051461064e5780635dd3fc9d14610661575f80fd5b80634d99c776146105c15780634e79238f146105d45780634ef4c3e11461060257806351dff98914610615575f80fd5b806324a3d6221161038357806341a18d2c1161035357806341a18d2c1461053f57806341c728b914610569578063425fad581461057c57806347ef3b3b1461058f5780634a584432146105a2575f80fd5b806324a3d622146104ed57806326782247146105005780632bc7e29e146105135780634088c73e14610532575f80fd5b806310b98338116103be57806310b983381461045d5780631ededc911461049a57806321af4569146104af57806324008a62146104da575f80fd5b806302c3bcbb146103ef57806304ef9d581461042157806308e0225c1461042a5780630db4b4e514610454575b5f80fd5b61040e6103fd366004613082565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61040e60225481565b61040e61043836600461309d565b601360209081525f928352604080842090915290825290205481565b61040e601d5481565b61048a61046b36600461309d565b602c60209081525f928352604080842090915290825290205460ff1681565b6040519015158152602001610418565b6104ad6104a83660046130d4565b610a80565b005b601e546104c2906001600160a01b031681565b6040516001600160a01b039091168152602001610418565b61040e6104e836600461312b565b610af8565b600a546104c2906001600160a01b031681565b6001546104c2906001600160a01b031681565b61040e610521366004613082565b60166020525f908152604090205481565b60185461048a9060ff1681565b61040e61054d36600461309d565b601260209081525f928352604080842090915290825290205481565b6104ad610577366004613179565b610baf565b60185461048a9062010000900460ff1681565b6104ad61059d3660046131bc565b610c26565b61040e6105b0366004613082565b601f6020525f908152604090205481565b61040e6105cf366004613241565b610cfe565b6105e76105e2366004613179565b610d1f565b60408051938452602084019290925290820152606001610418565b61040e61061036600461325b565b610d59565b6104ad610623366004613179565b610f31565b6105e7610636366004613082565b610f7d565b6104c2610649366004613299565b610fb4565b6104ad61065c36600461325b565b610fdc565b61040e61066f366004613082565b602b6020525f908152604090205481565b6105e761068e366004613082565b611052565b61040e6106a13660046132b0565b611066565b6104ad6106b436600461312b565b6112b6565b6104ad6106c73660046132b0565b611358565b61040e601c5481565b6106fd6106e3366004613082565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b039091168152602001610418565b60185461048a90610100900460ff1681565b601b546104c2906001600160a01b031681565b6004546104c2906001600160a01b031681565b60395461048a9060ff1681565b61040e610768366004613082565b60146020525f908152604090205481565b61048a610787366004613082565b602d6020525f908152604090205460ff1681565b6015546104c2906001600160a01b031681565b61040e60075481565b6107ca6107c5366004613310565b6113fa565b60405161041893929190613357565b6025546104c2906001600160a01b031681565b6037546106fd906001600160601b031681565b6020546104c2906001600160a01b031681565b610849610820366004613082565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff909116602083015201610418565b6002546104c2906001600160a01b031681565b61040e61088e366004613082565b602a6020525f908152604090205481565b61040e6108ad36600461312b565b6114a7565b61040e60175481565b6033546001600160a01b03166104c2565b6108e16a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b039091168152602001610418565b6021546104c2906001600160a01b031681565b6031546104c2906001600160a01b031681565b61040e61092d3660046132b0565b6114f3565b6026546104c2906001600160a01b031681565b6106fd5f81565b6039546104c29061010090046001600160a01b031681565b61040e61097236600461325b565b61166c565b6104c2610985366004613380565b6119f7565b6003546104c2906001600160a01b031681565b61048a6109ab366004613082565b60386020525f908152604090205460ff1681565b6108496109cd366004613082565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61048a610a043660046133aa565b611a2b565b61040e60055481565b61040e610a2036600461325b565b611a6f565b6104ad610a33366004613421565b611abb565b61048a610a4636600461309d565b603260209081525f928352604080842090915290825290205460ff1681565b5f546104c2906001600160a01b031681565b61040e601a5481565b6031546001600160a01b031615610af1576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610ac390869089906004016134b4565b5f604051808303815f87803b158015610ada575f80fd5b505af1158015610aec573d5f803e3d5ffd5b505050505b5050505050565b5f610b01611bb0565b610b0c856003611c00565b610b1d610b1886611c4e565b611c70565b5f6040518060200160405280876001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b8991906134ce565b90529050610b978682611cb8565b610ba2868583611e4f565b5f9150505b949350505050565b6031546001600160a01b031615610c20576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610bf290869088906004016134b4565b5f604051808303815f87803b158015610c09575f80fd5b505af1158015610c1b573d5f803e3d5ffd5b505050505b50505050565b6031546001600160a01b031615610cf6576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d1690610c699086908a906004016134b4565b5f604051808303815f87803b158015610c80575f80fd5b505af1158015610c92573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610cc89087908a906004016134b4565b5f604051808303815f87803b158015610cdf575f80fd5b505af1158015610cf1573d5f803e3d5ffd5b505050505b505050505050565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b5f805f805f80610d328a8a8a8a5f611fd3565b925092509250826014811115610d4a57610d4a6134e5565b9a919950975095505050505050565b5f610d62611bb0565b610d6c845f611c00565b610d78610b1885611c4e565b6001600160a01b0384165f9081526027602052604081205490819003610dde5760405162461bcd60e51b815260206004820152601660248201527506d61726b657420737570706c792063617020697320360541b60448201526064015b60405180910390fd5b5f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e1b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e3f91906134ce565b90505f6040518060200160405280886001600160a01b031663182df0f56040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e89573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ead91906134ce565b905290505f610ebd828488612080565b905083811115610f0f5760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420737570706c79206361702072656163686564000000000000006044820152606401610dd5565b610f18886120a0565b610f22888861220d565b5f9450505050505b9392505050565b80151580610f3d575081155b610baf5760405162461bcd60e51b815260206004820152601160248201527072656465656d546f6b656e73207a65726f60781b6044820152606401610dd5565b5f805f805f80610f90875f805f80611fd3565b925092509250826014811115610fa857610fa86134e5565b97919650945092505050565b600d8181548110610fc3575f80fd5b5f918252602090912001546001600160a01b0316905081565b6031546001600160a01b03161561104d576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d169061101f90859087906004016134b4565b5f604051808303815f87803b158015611036575f80fd5b505af1158015611048573d5f803e3d5ffd5b505050505b505050565b5f805f805f80610f90875f805f6001611fd3565b5f61106f611bb0565b61107a866005611c00565b6025546001600160a01b0316158015906110a257506025546001600160a01b03858116911614155b156110af575060016112ad565b6110bb610b1886611c4e565b6015545f906001600160a01b0388811691161461114d576110de610b1888611c4e565b6040516395dd919360e01b81526001600160a01b0385811660048301528816906395dd919390602401602060405180830381865afa158015611122573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061114691906134ce565b90506111bc565b601554604051633c617c9160e11b81526001600160a01b038681166004830152909116906378c2f92290602401602060405180830381865afa158015611195573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111b991906134ce565b90505b6001600160a01b0387165f908152602d602052604090205460ff168061120657506001600160a01b038085165f908152603260209081526040808320938b168352929052205460ff165b15611224578083111561121e5760115b9150506112ad565b5f611216565b5f80611234865f805f6001611fd3565b9193509091505f905082601481111561124f5761124f6134e5565b1461127057816014811115611266576112666134e5565b93505050506112ad565b805f0361127e576003611266565b6112986040518060200160405280600554815250846123ab565b8511156112a6576011611266565b5f93505050505b95945050505050565b6031546001600160a01b031615610c20576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d16906112f990869088906004016134b4565b5f604051808303815f87803b158015611310575f80fd5b505af1158015611322573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610bf290859088906004016134b4565b6031546001600160a01b031615610af1576031546040516367994e8b60e11b81526001600160a01b039091169063cf329d169061139b90859089906004016134b4565b5f604051808303815f87803b1580156113b2575f80fd5b505af11580156113c4573d5f803e3d5ffd5b50506031546040516367994e8b60e11b81526001600160a01b03909116925063cf329d169150610ac390869089906004016134b4565b60366020525f9081526040902080548190611414906134f9565b80601f0160208091040260200160405190810160405280929190818152602001828054611440906134f9565b801561148b5780601f106114625761010080835404028352916020019161148b565b820191905f5260205f20905b81548152906001019060200180831161146e57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6114b0611bb0565b6114bb856006611c00565b5f6114c78686856123c2565b905080156114d6579050610ba7565b6114df866120a0565b6114e9868661220d565b610ba2868561220d565b5f6114fc611bb0565b611507866004611c00565b5f61151187611c4e565b905061151c81611c70565b6001600160a01b0384165f90815260028201602052604090205460ff16611544576013611216565b6015546001600160a01b0387811691161461156557611565610b1887611c4e565b856001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156115a1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115c59190613531565b6001600160a01b0316876001600160a01b0316635fe3b5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561160a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061162e9190613531565b6001600160a01b031614611643576002611216565b61164c876120a0565b611656878561220d565b611660878661220d565b5f979650505050505050565b5f611675611bb0565b611680846002611c00565b61168c610b1885611c4e565b611696838561245b565b6001600160a01b0384165f908152601f6020526040812054908190036116f75760405162461bcd60e51b815260206004820152601660248201527506d61726b657420626f72726f772063617020697320360541b6044820152606401610dd5565b61170085611c4e565b6001600160a01b0385165f908152600291909101602052604090205460ff166117b557336001600160a01b038616146117735760405162461bcd60e51b815260206004820152601560248201527439b2b73232b91036bab9ba103132903b2a37b5b2b760591b6044820152606401610dd5565b5f61177e868661251e565b90505f816014811115611793576117936134e5565b146117b3578060148111156117aa576117aa6134e5565b92505050610f2a565b505b6039546040516388142b6b60e01b81526001600160a01b0387811660048301525f928392610100909104909116906388142b6b906024016040805180830381865afa158015611806573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061182a919061354c565b91509150815f148061183a575080155b1561184b57600d9350505050610f2a565b5f6118b5886001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa15801561188b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118af91906134ce565b876125f1565b9050838111156119075760405162461bcd60e51b815260206004820152601960248201527f6d61726b657420626f72726f77206361702072656163686564000000000000006044820152606401610dd5565b5f80611916898b5f8b5f612626565b9193509091505f9050826014811115611931576119316134e5565b1461195557816014811115611948576119486134e5565b9650505050505050610f2a565b8015611962576004611948565b5f60405180602001604052808c6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119aa573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119ce91906134ce565b905290506119dc8b82611cb8565b6119e78b8b83611e4f565b5f9b9a5050505050505050505050565b6008602052815f5260405f208181548110611a10575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611a5557611a556134e5565b815260208101919091526040015f205460ff169392505050565b5f611a78611bb0565b611a83846001611c00565b5f611a8f8585856123c2565b90508015611a9e579050610f2a565b611aa7856120a0565b611ab1858561220d565b5f95945050505050565b611ac3612688565b848381148015611ad257508082145b611b0e5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610dd5565b5f5b81811015610c1b57611b47888883818110611b2d57611b2d61356e565b9050602002016020810190611b429190613082565b6126d2565b611ba8888883818110611b5c57611b5c61356e565b9050602002016020810190611b719190613082565b878784818110611b8357611b8361356e565b90506020020135868685818110611b9c57611b9c61356e565b90506020020135612720565b600101611b10565b60185462010000900460ff1615611bfe5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610dd5565b565b611c0a8282611a2b565b15611c4a5760405162461bcd60e51b815260206004820152601060248201526f1858dd1a5bdb881a5cc81c185d5cd95960821b6044820152606401610dd5565b5050565b5f60095f611c5c5f85610cfe565b81526020019081526020015f209050919050565b805460ff16611cb55760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610dd5565b50565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611ce461289a565b83549091505f90611d059063ffffffff80851691600160e01b9004166128d3565b90508015801590611d1557508215155b15611e24575f611d84876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611d5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d7e91906134ce565b8761290c565b90505f611d918386612929565b90505f825f03611daf5760405180602001604052805f815250611db9565b611db9828461296a565b604080516020810190915288546001600160e01b03168152909150611e0290611de290836129ad565b516040805180820190915260038152620c8c8d60ea1b60208201526129d6565b6001600160e01b0316600160e01b63ffffffff87160217875550610cf6915050565b8015610cf657835463ffffffff8316600160e01b026001600160e01b03909116178455505050505050565b601b546001600160a01b031615611e6857611e68612a04565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b03909216908190559080158015611ec457506a0c097ce7bc90715b34b9f160241b8210155b15611eda57506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611ef085856128d3565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f91611f4991611f43918a16906395dd919390602401602060405180830381865afa158015611d5a573d5f803e3d5ffd5b83612b76565b6001600160a01b0387165f90815260146020526040902054909150611f6e90826125f1565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e906120199030908f908f908f908f908f90600401613582565b606060405180830381865afa158015612034573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061205891906135dd565b925092509250826014811115612070576120706134e5565b9b919a5098509650505050505050565b5f8061208c8585612b9d565b90506112ad61209a82612bc3565b846125f1565b6001600160a01b0381165f908152601060209081526040808320602b90925282205490916120cc61289a565b83549091505f906120ed9063ffffffff80851691600160e01b9004166128d3565b905080158015906120fd57508215155b156121e3575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561213f573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061216391906134ce565b90505f6121708386612929565b90505f825f0361218e5760405180602001604052805f815250612198565b612198828461296a565b604080516020810190915288546001600160e01b031681529091506121c190611de290836129ad565b6001600160e01b0316600160e01b63ffffffff87160217875550610af1915050565b8015610af157835463ffffffff8316600160e01b026001600160e01b039091161784555050505050565b601b546001600160a01b03161561222657612226612a04565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b0390921690819055908015801561228257506a0c097ce7bc90715b34b9f160241b8210155b1561229857506a0c097ce7bc90715b34b9f160241b5b5f60405180602001604052806122ae85856128d3565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f9161232291908816906370a0823190602401602060405180830381865afa1580156122fe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611f4391906134ce565b6001600160a01b0386165f9081526014602052604090205490915061234790826125f1565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f806123b78484612b9d565b9050610ba781612bc3565b5f6123cf610b1885611c4e565b6123d884611c4e565b6001600160a01b0384165f908152600291909101602052604090205460ff1661240257505f610f2a565b5f806124118587865f80612626565b9193509091505f905082601481111561242c5761242c6134e5565b14612443578160148111156117aa576117aa6134e5565b80156124505760046117aa565b5f9695505050505050565b6001600160a01b0382165f908152603560205260408120546001600160601b0316906124878284610cfe565b5f81815260096020526040902060060154909150600160601b900460ff166124c2576040516305b80c7960e41b815260040160405180910390fd5b6001600160601b038216158015906124f557506001600160601b0382165f9081526036602052604090206002015460ff16155b15610c2057604051632da4cc0560e01b81526001600160601b0383166004820152602401610dd5565b5f61252a836007611c00565b5f61253484611c4e565b905061253f81611c70565b6001600160a01b0383165f90815260028201602052604090205460ff161561256a575f915050610d19565b6001600160a01b038084165f8181526002840160209081526040808320805460ff191660019081179091556008835281842080549182018155845291832090910180549489166001600160a01b031990951685179055519192917f3ab23ab0d51cccc0c3085aec51f99228625aa1a922b3a8ca89a26b0f2027a1a59190a3505f9392505050565b5f610f2a8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612bda565b5f80808084600181111561263c5761263c6134e5565b0361264a5761264a88612c13565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e906120199030908f908f908f908f908f90600401613582565b5f546001600160a01b03163314611bfe5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610dd5565b6001600160a01b038116611cb55760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610dd5565b61272c610b1884611c4e565b6001600160a01b0383165f908152602b602052604090205482146127a857612753836120a0565b6001600160a01b0383165f818152602b602052604090819020849055517fa9ff26899e4982e7634afa9f70115dcfb61a17d6e8cdd91aa837671d0ff40ba69061279f9085815260200190565b60405180910390a25b6001600160a01b0383165f908152602a6020526040902054811461104d575f6040518060200160405280856001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561280e573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061283291906134ce565b905290506128408482611cb8565b6001600160a01b0384165f818152602a602052604090819020849055517f0c62c1bc89ec4c40dccb4d21543e782c5ba43897c0075d108d8964181ea3c51b9061288c9085815260200190565b60405180910390a250505050565b5f6128ce4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612d2a565b905090565b5f610f2a8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612d51565b5f610f2a61292284670de0b6b3a7640000612929565b8351612d7f565b5f610f2a83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612db1565b60408051602081019091525f815260405180602001604052806129a461299e866a0c097ce7bc90715b34b9f160241b612929565b85612d7f565b90529392505050565b60408051602081019091525f815260405180602001604052806129a4855f0151855f01516125f1565b5f81600160e01b84106129fc5760405162461bcd60e51b8152600401610dd59190613608565b509192915050565b601c541580612a145750601c5443105b15612a1b57565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015612a65573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a8991906134ce565b9050805f03612a96575050565b5f80612aa443601c546128d3565b90505f612ab3601a5483612929565b9050808410612ac457809250612ac8565b8392505b601d54831015612ad9575050505050565b43601c55601b54612af7906001600160a01b03878116911685612e01565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015610ada575f80fd5b5f6a0c097ce7bc90715b34b9f160241b612b9384845f0151612929565b610f2a919061362e565b60408051602081019091525f815260405180602001604052806129a4855f015185612929565b80515f90610d1990670de0b6b3a76400009061362e565b5f80612be6848661364d565b90508285821015612c0a5760405162461bcd60e51b8152600401610dd59190613608565b50949350505050565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015612c8957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311612c6b575b505083519394505f925050505b81811015610af157836001600160a01b031663a9c3cab1848381518110612cbf57612cbf61356e565b60200260200101516040518263ffffffff1660e01b8152600401612cf291906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015612d09575f80fd5b505af1158015612d1b573d5f803e3d5ffd5b50505050806001019050612c96565b5f8164010000000084106129fc5760405162461bcd60e51b8152600401610dd59190613608565b5f8184841115612d745760405162461bcd60e51b8152600401610dd59190613608565b50610ba78385613660565b5f610f2a83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612e53565b5f831580612dbd575082155b15612dc957505f610f2a565b5f612dd48486613673565b905083612de1868361362e565b148390612c0a5760405162461bcd60e51b8152600401610dd59190613608565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261104d908490612e7e565b5f8183612e735760405162461bcd60e51b8152600401610dd59190613608565b50610ba7838561362e565b5f612ed2826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316612f519092919063ffffffff16565b905080515f1480612ef2575080806020019051810190612ef2919061368a565b61104d5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610dd5565b6060610ba784845f85855f80866001600160a01b03168587604051612f7691906136a9565b5f6040518083038185875af1925050503d805f8114612fb0576040519150601f19603f3d011682016040523d82523d5f602084013e612fb5565b606091505b5091509150612fc687838387612fd1565b979650505050505050565b6060831561303f5782515f03613038576001600160a01b0385163b6130385760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610dd5565b5081610ba7565b610ba783838151156130545781518083602001fd5b8060405162461bcd60e51b8152600401610dd59190613608565b6001600160a01b0381168114611cb5575f80fd5b5f60208284031215613092575f80fd5b8135610f2a8161306e565b5f80604083850312156130ae575f80fd5b82356130b98161306e565b915060208301356130c98161306e565b809150509250929050565b5f805f805f60a086880312156130e8575f80fd5b85356130f38161306e565b945060208601356131038161306e565b935060408601356131138161306e565b94979396509394606081013594506080013592915050565b5f805f806080858703121561313e575f80fd5b84356131498161306e565b935060208501356131598161306e565b925060408501356131698161306e565b9396929550929360600135925050565b5f805f806080858703121561318c575f80fd5b84356131978161306e565b935060208501356131a78161306e565b93969395505050506040820135916060013590565b5f805f805f8060c087890312156131d1575f80fd5b86356131dc8161306e565b955060208701356131ec8161306e565b945060408701356131fc8161306e565b9350606087013561320c8161306e565b9598949750929560808101359460a0909101359350915050565b80356001600160601b038116811461323c575f80fd5b919050565b5f8060408385031215613252575f80fd5b6130b983613226565b5f805f6060848603121561326d575f80fd5b83356132788161306e565b925060208401356132888161306e565b929592945050506040919091013590565b5f602082840312156132a9575f80fd5b5035919050565b5f805f805f60a086880312156132c4575f80fd5b85356132cf8161306e565b945060208601356132df8161306e565b935060408601356132ef8161306e565b925060608601356132ff8161306e565b949793965091946080013592915050565b5f60208284031215613320575f80fd5b610f2a82613226565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6133696060830186613329565b931515602083015250901515604090910152919050565b5f8060408385031215613391575f80fd5b823561339c8161306e565b946020939093013593505050565b5f80604083850312156133bb575f80fd5b82356133c68161306e565b91506020830135600981106130c9575f80fd5b5f8083601f8401126133e9575f80fd5b50813567ffffffffffffffff811115613400575f80fd5b6020830191508360208260051b850101111561341a575f80fd5b9250929050565b5f805f805f8060608789031215613436575f80fd5b863567ffffffffffffffff8082111561344d575f80fd5b6134598a838b016133d9565b90985096506020890135915080821115613471575f80fd5b61347d8a838b016133d9565b90965094506040890135915080821115613495575f80fd5b506134a289828a016133d9565b979a9699509497509295939492505050565b6001600160a01b0392831681529116602082015260400190565b5f602082840312156134de575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b600181811c9082168061350d57607f821691505b60208210810361352b57634e487b7160e01b5f52602260045260245ffd5b50919050565b5f60208284031215613541575f80fd5b8151610f2a8161306e565b5f806040838503121561355d575f80fd5b505080516020909101519092909150565b634e487b7160e01b5f52603260045260245ffd5b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101600283106135cc57634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f606084860312156135ef575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610f2a6020830184613329565b634e487b7160e01b5f52601160045260245ffd5b5f8261364857634e487b7160e01b5f52601260045260245ffd5b500490565b80820180821115610d1957610d1961361a565b81810381811115610d1957610d1961361a565b8082028115828204841417610d1957610d1961361a565b5f6020828403121561369a575f80fd5b81518015158114610f2a575f80fd5b5f82518060208501845e5f92019182525091905056fea2646970667358221220a577d175a4a6a3d87eb45e30d1f3b89394de97350923b50e6a0238ad20ddede864736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This facet contains all the hooks used while transferring the assets", @@ -2129,6 +2142,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "flashLoanPaused()": { "notice": "Whether flash loans are paused system-wide" }, @@ -2277,7 +2293,7 @@ "storageLayout": { "storage": [ { - "astId": 1677, + "astId": 9780, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "admin", "offset": 0, @@ -2285,7 +2301,7 @@ "type": "t_address" }, { - "astId": 1680, + "astId": 9783, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "pendingAdmin", "offset": 0, @@ -2293,7 +2309,7 @@ "type": "t_address" }, { - "astId": 1683, + "astId": 9786, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "comptrollerImplementation", "offset": 0, @@ -2301,7 +2317,7 @@ "type": "t_address" }, { - "astId": 1686, + "astId": 9789, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -2309,15 +2325,15 @@ "type": "t_address" }, { - "astId": 1693, + "astId": 9796, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)992" + "type": "t_contract(ResilientOracleInterface)8467" }, { - "astId": 1696, + "astId": 9799, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "closeFactorMantissa", "offset": 0, @@ -2325,7 +2341,7 @@ "type": "t_uint256" }, { - "astId": 1699, + "astId": 9802, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -2333,7 +2349,7 @@ "type": "t_uint256" }, { - "astId": 1702, + "astId": 9805, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "maxAssets", "offset": 0, @@ -2341,23 +2357,23 @@ "type": "t_uint256" }, { - "astId": 1709, + "astId": 9812, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)" }, { - "astId": 1743, + "astId": 9846, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)" }, { - "astId": 1746, + "astId": 9849, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "pauseGuardian", "offset": 0, @@ -2365,7 +2381,7 @@ "type": "t_address" }, { - "astId": 1749, + "astId": 9852, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -2373,7 +2389,7 @@ "type": "t_bool" }, { - "astId": 1752, + "astId": 9855, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -2381,7 +2397,7 @@ "type": "t_bool" }, { - "astId": 1755, + "astId": 9858, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "transferGuardianPaused", "offset": 22, @@ -2389,7 +2405,7 @@ "type": "t_bool" }, { - "astId": 1758, + "astId": 9861, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -2397,7 +2413,7 @@ "type": "t_bool" }, { - "astId": 1763, + "astId": 9866, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "mintGuardianPaused", "offset": 0, @@ -2405,7 +2421,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1768, + "astId": 9871, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -2413,15 +2429,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1780, + "astId": 9883, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)32634)dyn_storage" + "type": "t_array(t_contract(VToken)58633)dyn_storage" }, { - "astId": 1783, + "astId": 9886, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusRate", "offset": 0, @@ -2429,7 +2445,7 @@ "type": "t_uint256" }, { - "astId": 1788, + "astId": 9891, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusSpeeds", "offset": 0, @@ -2437,23 +2453,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1794, + "astId": 9897, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1800, + "astId": 9903, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1807, + "astId": 9910, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusSupplierIndex", "offset": 0, @@ -2461,7 +2477,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1814, + "astId": 9917, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -2469,7 +2485,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1819, + "astId": 9922, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusAccrued", "offset": 0, @@ -2477,15 +2493,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1823, + "astId": 9926, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)25733" + "type": "t_contract(VAIControllerInterface)51683" }, { - "astId": 1828, + "astId": 9931, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "mintedVAIs", "offset": 0, @@ -2493,7 +2509,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1831, + "astId": 9934, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "vaiMintRate", "offset": 0, @@ -2501,7 +2517,7 @@ "type": "t_uint256" }, { - "astId": 1834, + "astId": 9937, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -2509,7 +2525,7 @@ "type": "t_bool" }, { - "astId": 1836, + "astId": 9939, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -2517,7 +2533,7 @@ "type": "t_bool" }, { - "astId": 1839, + "astId": 9942, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "protocolPaused", "offset": 2, @@ -2525,7 +2541,7 @@ "type": "t_bool" }, { - "astId": 1842, + "astId": 9945, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusVAIRate", "offset": 0, @@ -2533,7 +2549,7 @@ "type": "t_uint256" }, { - "astId": 1848, + "astId": 9951, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -2541,7 +2557,7 @@ "type": "t_uint256" }, { - "astId": 1850, + "astId": 9953, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "vaiVaultAddress", "offset": 0, @@ -2549,7 +2565,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9955, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "releaseStartBlock", "offset": 0, @@ -2557,7 +2573,7 @@ "type": "t_uint256" }, { - "astId": 1854, + "astId": 9957, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "minReleaseAmount", "offset": 0, @@ -2565,7 +2581,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9963, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "borrowCapGuardian", "offset": 0, @@ -2573,7 +2589,7 @@ "type": "t_address" }, { - "astId": 1865, + "astId": 9968, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "borrowCaps", "offset": 0, @@ -2581,7 +2597,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1871, + "astId": 9974, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "treasuryGuardian", "offset": 0, @@ -2589,7 +2605,7 @@ "type": "t_address" }, { - "astId": 1874, + "astId": 9977, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "treasuryAddress", "offset": 0, @@ -2597,7 +2613,7 @@ "type": "t_address" }, { - "astId": 1877, + "astId": 9980, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "treasuryPercent", "offset": 0, @@ -2605,7 +2621,7 @@ "type": "t_uint256" }, { - "astId": 1885, + "astId": 9988, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -2613,7 +2629,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9993, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "lastContributorBlock", "offset": 0, @@ -2621,7 +2637,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1895, + "astId": 9998, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "liquidatorContract", "offset": 0, @@ -2629,15 +2645,15 @@ "type": "t_address" }, { - "astId": 1901, + "astId": 10004, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1660" + "type": "t_contract(ComptrollerLensInterface)9761" }, { - "astId": 1909, + "astId": 10012, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "supplyCaps", "offset": 0, @@ -2645,7 +2661,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1915, + "astId": 10018, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "accessControl", "offset": 0, @@ -2653,7 +2669,7 @@ "type": "t_address" }, { - "astId": 1922, + "astId": 10025, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_actionPaused", "offset": 0, @@ -2661,7 +2677,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1930, + "astId": 10033, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -2669,7 +2685,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1935, + "astId": 10038, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -2677,7 +2693,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1945, + "astId": 10048, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "approvedDelegates", "offset": 0, @@ -2685,7 +2701,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1953, + "astId": 10056, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -2693,23 +2709,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1972, + "astId": 10075, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)" }, { - "astId": 1977, + "astId": 10080, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)" }, { - "astId": 1980, + "astId": 10083, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "_facetAddresses", "offset": 0, @@ -2717,15 +2733,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1987, + "astId": 10090, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)22911" + "type": "t_contract(IPrime)42902" }, { - "astId": 1997, + "astId": 10100, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -2733,7 +2749,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 2003, + "astId": 10106, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "xvs", "offset": 0, @@ -2741,7 +2757,7 @@ "type": "t_address" }, { - "astId": 2006, + "astId": 10109, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "xvsVToken", "offset": 0, @@ -2749,7 +2765,7 @@ "type": "t_address" }, { - "astId": 2028, + "astId": 10131, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "userPoolId", "offset": 0, @@ -2757,15 +2773,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2034, + "astId": 10137, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)2023_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)10126_storage)" }, { - "astId": 2037, + "astId": 10140, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "lastPoolId", "offset": 0, @@ -2773,7 +2789,7 @@ "type": "t_uint96" }, { - "astId": 2045, + "astId": 10148, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -2781,12 +2797,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2048, + "astId": 10151, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 10158, + "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)8437" } ], "types": { @@ -2807,8 +2831,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)32634)dyn_storage": { - "base": "t_contract(VToken)32634", + "t_array(t_contract(VToken)58633)dyn_storage": { + "base": "t_contract(VToken)58633", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -2823,37 +2847,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1660": { + "t_contract(ComptrollerLensInterface)9761": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)22911": { + "t_contract(IDeviationBoundedOracle)8437": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)42902": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)992": { + "t_contract(ResilientOracleInterface)8467": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)25733": { + "t_contract(VAIControllerInterface)51683": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)32634": { + "t_contract(VToken)58633": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)32634)dyn_storage" + "value": "t_array(t_contract(VToken)58633)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -2883,19 +2912,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1967_storage" + "value": "t_struct(FacetFunctionSelectors)10070_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1775_storage" + "value": "t_struct(VenusMarketState)9878_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2911,12 +2940,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1961_storage" + "value": "t_struct(FacetAddressAndPosition)10064_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -2925,31 +2954,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)2023_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)10126_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)2023_storage" + "value": "t_struct(PoolData)10126_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11427", + "key": "t_userDefinedValueType(PoolMarketId)19777", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1736_storage" + "value": "t_struct(Market)9839_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1961_storage": { + "t_struct(FacetAddressAndPosition)10064_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1958, + "astId": 10061, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "facetAddress", "offset": 0, @@ -2957,7 +2986,7 @@ "type": "t_address" }, { - "astId": 1960, + "astId": 10063, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "functionSelectorPosition", "offset": 20, @@ -2967,12 +2996,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1967_storage": { + "t_struct(FacetFunctionSelectors)10070_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1964, + "astId": 10067, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "functionSelectors", "offset": 0, @@ -2980,7 +3009,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1966, + "astId": 10069, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "facetAddressPosition", "offset": 0, @@ -2990,12 +3019,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1736_storage": { + "t_struct(Market)9839_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1712, + "astId": 9815, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isListed", "offset": 0, @@ -3003,7 +3032,7 @@ "type": "t_bool" }, { - "astId": 1715, + "astId": 9818, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -3011,7 +3040,7 @@ "type": "t_uint256" }, { - "astId": 1720, + "astId": 9823, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "accountMembership", "offset": 0, @@ -3019,7 +3048,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1723, + "astId": 9826, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isVenus", "offset": 0, @@ -3027,7 +3056,7 @@ "type": "t_bool" }, { - "astId": 1726, + "astId": 9829, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -3035,7 +3064,7 @@ "type": "t_uint256" }, { - "astId": 1729, + "astId": 9832, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -3043,7 +3072,7 @@ "type": "t_uint256" }, { - "astId": 1732, + "astId": 9835, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "poolId", "offset": 0, @@ -3051,7 +3080,7 @@ "type": "t_uint96" }, { - "astId": 1735, + "astId": 9838, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isBorrowAllowed", "offset": 12, @@ -3061,12 +3090,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)2023_storage": { + "t_struct(PoolData)10126_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 2012, + "astId": 10115, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "label", "offset": 0, @@ -3074,7 +3103,7 @@ "type": "t_string_storage" }, { - "astId": 2016, + "astId": 10119, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "vTokens", "offset": 0, @@ -3082,7 +3111,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 2019, + "astId": 10122, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "isActive", "offset": 0, @@ -3090,7 +3119,7 @@ "type": "t_bool" }, { - "astId": 2022, + "astId": 10125, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -3100,12 +3129,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1775_storage": { + "t_struct(VenusMarketState)9878_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1771, + "astId": 9874, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "index", "offset": 0, @@ -3113,7 +3142,7 @@ "type": "t_uint224" }, { - "astId": 1774, + "astId": 9877, "contract": "contracts/Comptroller/Diamond/facets/PolicyFacet.sol:PolicyFacet", "label": "block", "offset": 28, @@ -3143,7 +3172,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11427": { + "t_userDefinedValueType(PoolMarketId)19777": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bsctestnet/RewardFacet.json b/deployments/bsctestnet/RewardFacet.json index a1aa3595b..0863283f0 100644 --- a/deployments/bsctestnet/RewardFacet.json +++ b/deployments/bsctestnet/RewardFacet.json @@ -1,5 +1,5 @@ { - "address": "0x0bc7922Cc08Ea32E196d25805558a84dF54beC6a", + "address": "0x977515f4043111ba5e44C09D3Af071ba5B9B34a1", "abi": [ { "inputs": [], @@ -703,6 +703,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -1346,28 +1359,28 @@ "type": "function" } ], - "transactionHash": "0x296b81551dbd81f0eb42bfca1c290064faad1da201b26246ac32fffe376eb24d", + "transactionHash": "0xed791a85212aa2232af0633fa0abf837b265a02a102c4dc3c739c15045f99cb9", "receipt": { "to": null, - "from": "0x33C6476F88eeA28D7E7900F759B4597704Ef95B7", - "contractAddress": "0x0bc7922Cc08Ea32E196d25805558a84dF54beC6a", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0x977515f4043111ba5e44C09D3Af071ba5B9B34a1", "transactionIndex": 0, - "gasUsed": "2419503", + "gasUsed": "2493418", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x8b6d5146c31f30113266f2a96a2922fa7bbf6bfb0b4f1afdcd0a1b917be196db", - "transactionHash": "0x296b81551dbd81f0eb42bfca1c290064faad1da201b26246ac32fffe376eb24d", + "blockHash": "0x557a68cce6165b39c88df0f62d0368c13d666840505c0da029c0b86713b6e623", + "transactionHash": "0xed791a85212aa2232af0633fa0abf837b265a02a102c4dc3c739c15045f99cb9", "logs": [], - "blockNumber": 70275001, - "cumulativeGasUsed": "2419503", + "blockNumber": 102774082, + "cumulativeGasUsed": "2493418", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 7, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"VenusGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"VenusSeized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantXVS\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"collateral\",\"type\":\"bool\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimVenusAsCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSVTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"seizeVenus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the methods related to the reward functionality\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_grantXVS(address,uint256)\":{\"details\":\"Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall Note: If there is not enough XVS, we do not perform the transfer all\",\"params\":{\"amount\":\"The amount of XVS to (possibly) transfer\",\"recipient\":\"The address of the recipient to transfer XVS to\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"claimVenus(address)\":{\"params\":{\"holder\":\"The address to claim XVS for\"}},\"claimVenus(address,address[])\":{\"params\":{\"holder\":\"The address to claim XVS for\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenus(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim XVS earned by borrowing\",\"holders\":\"The addresses to claim XVS for\",\"suppliers\":\"Whether or not to claim XVS earned by supplying\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenus(address[],address[],bool,bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim XVS earned by borrowing\",\"collateral\":\"Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\",\"holders\":\"The addresses to claim XVS for\",\"suppliers\":\"Whether or not to claim XVS earned by supplying\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenusAsCollateral(address)\":{\"params\":{\"holder\":\"The address to claim XVS for\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"getXVSVTokenAddress()\":{\"returns\":{\"_0\":\"The address of XVS vToken\"}},\"seizeVenus(address[],address)\":{\"details\":\"Seize XVS tokens from the specified holders and transfer to recipient\",\"params\":{\"holders\":\"Addresses of the XVS holders\",\"recipient\":\"Address of the XVS token recipient\"},\"returns\":{\"_0\":\"The total amount of XVS tokens seized and transferred to recipient\"}}},\"title\":\"RewardFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedBorrowerVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a borrower\"},\"DistributedSupplierVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a supplier\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"VenusGranted(address,uint256)\":{\"notice\":\"Emitted when Venus is granted by admin\"},\"VenusSeized(address,uint256)\":{\"notice\":\"Emitted when XVS are seized for the holder\"}},\"kind\":\"user\",\"methods\":{\"_grantXVS(address,uint256)\":{\"notice\":\"Transfer XVS to the recipient\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"claimVenus(address)\":{\"notice\":\"Claim all the xvs accrued by holder in all markets and VAI\"},\"claimVenus(address,address[])\":{\"notice\":\"Claim all the xvs accrued by holder in the specified markets\"},\"claimVenus(address[],address[],bool,bool)\":{\"notice\":\"Claim all xvs accrued by the holders\"},\"claimVenus(address[],address[],bool,bool,bool)\":{\"notice\":\"Claim all xvs accrued by the holders\"},\"claimVenusAsCollateral(address)\":{\"notice\":\"Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"getXVSVTokenAddress()\":{\"notice\":\"Returns the XVS vToken address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"seizeVenus(address[],address)\":{\"notice\":\"Seize XVS rewards allocated to holders\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract provides the external functions related to all claims and rewards of the protocol\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/RewardFacet.sol\":\"RewardFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/RewardFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { IRewardFacet } from \\\"../interfaces/IRewardFacet.sol\\\";\\nimport { XVSRewardsHelper } from \\\"./XVSRewardsHelper.sol\\\";\\nimport { VBep20Interface } from \\\"../../../Tokens/VTokens/VTokenInterfaces.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title RewardFacet\\n * @author Venus\\n * @dev This facet contains all the methods related to the reward functionality\\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\\n */\\ncontract RewardFacet is IRewardFacet, XVSRewardsHelper {\\n /// @notice Emitted when Venus is granted by admin\\n event VenusGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when XVS are seized for the holder\\n event VenusSeized(address indexed holder, uint256 amount);\\n\\n using SafeERC20 for IERC20;\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in all markets and VAI\\n * @param holder The address to claim XVS for\\n */\\n function claimVenus(address holder) public {\\n return claimVenus(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in the specified markets\\n * @param holder The address to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n */\\n function claimVenus(address holder, VToken[] memory vTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimVenus(holders, vTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all xvs accrued by the holders\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n */\\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\\n claimVenus(holders, vTokens, borrowers, suppliers, false);\\n }\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\\n * @param holder The address to claim XVS for\\n */\\n function claimVenusAsCollateral(address holder) external {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimVenus(holders, allMarkets, true, true, true);\\n }\\n\\n /**\\n * @notice Transfer XVS to the user with user's shortfall considered\\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\\n * @param user The address of the user to transfer XVS to\\n * @param amount The amount of XVS to (possibly) transfer\\n * @param shortfall The shortfall of the user\\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\\n * @return The amount of XVS which was NOT transferred to the user\\n */\\n function grantXVSInternal(\\n address user,\\n uint256 amount,\\n uint256 shortfall,\\n bool collateral\\n ) internal returns (uint256) {\\n // If the user is blacklisted, they can't get XVS rewards\\n require(\\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\\n \\\"Blacklisted\\\"\\n );\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n if (amount == 0 || amount > xvs_.balanceOf(address(this))) {\\n return amount;\\n }\\n\\n if (shortfall == 0) {\\n xvs_.safeTransfer(user, amount);\\n return 0;\\n }\\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\\n // anything, otherwise, we will transfer the pending xvs as collateral to\\n // vXVS token and mint vXVS for the user\\n //\\n // If mintBehalf failed, don't grant any xvs\\n require(collateral, \\\"bankrupt\\\");\\n\\n address xvsVToken_ = xvsVToken;\\n\\n xvs_.safeApprove(xvsVToken_, 0);\\n xvs_.safeApprove(xvsVToken_, amount);\\n require(VBep20Interface(xvsVToken_).mintBehalf(user, amount) == uint256(Error.NO_ERROR), \\\"mint behalf error\\\");\\n\\n // set venusAccrued[user] to 0\\n return 0;\\n }\\n\\n /*** Venus Distribution Admin ***/\\n\\n /**\\n * @notice Transfer XVS to the recipient\\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\\n * Note: If there is not enough XVS, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer XVS to\\n * @param amount The amount of XVS to (possibly) transfer\\n */\\n function _grantXVS(address recipient, uint256 amount) external {\\n ensureAdmin();\\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\\n require(amountLeft == 0, \\\"no xvs\\\");\\n emit VenusGranted(recipient, amount);\\n }\\n\\n /**\\n * @dev Seize XVS tokens from the specified holders and transfer to recipient\\n * @notice Seize XVS rewards allocated to holders\\n * @param holders Addresses of the XVS holders\\n * @param recipient Address of the XVS token recipient\\n * @return The total amount of XVS tokens seized and transferred to recipient\\n */\\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256) {\\n ensureAllowed(\\\"seizeVenus(address[],address)\\\");\\n\\n uint256 holdersLength = holders.length;\\n uint256 totalHoldings;\\n\\n updateAndDistributeRewardsInternal(holders, allMarkets, true, true);\\n for (uint256 j; j < holdersLength; ++j) {\\n address holder = holders[j];\\n uint256 userHolding = venusAccrued[holder];\\n\\n if (userHolding != 0) {\\n totalHoldings += userHolding;\\n delete venusAccrued[holder];\\n }\\n\\n emit VenusSeized(holder, userHolding);\\n }\\n\\n if (totalHoldings != 0) {\\n IERC20(xvs).safeTransfer(recipient, totalHoldings);\\n emit VenusGranted(recipient, totalHoldings);\\n }\\n\\n return totalHoldings;\\n }\\n\\n /**\\n * @notice Claim all xvs accrued by the holders\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\\n */\\n function claimVenus(\\n address[] memory holders,\\n VToken[] memory vTokens,\\n bool borrowers,\\n bool suppliers,\\n bool collateral\\n ) public {\\n uint256 holdersLength = holders.length;\\n\\n updateAndDistributeRewardsInternal(holders, vTokens, borrowers, suppliers);\\n for (uint256 j; j < holdersLength; ++j) {\\n address holder = holders[j];\\n\\n // If there is a positive shortfall, the XVS reward is accrued,\\n // but won't be granted to this holder\\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n holder,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n\\n uint256 value = venusAccrued[holder];\\n delete venusAccrued[holder];\\n\\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\\n\\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\\n if (returnAmount != 0) {\\n venusAccrued[holder] = returnAmount;\\n }\\n }\\n }\\n\\n /**\\n * @notice Update and distribute tokens\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n */\\n function updateAndDistributeRewardsInternal(\\n address[] memory holders,\\n VToken[] memory vTokens,\\n bool borrowers,\\n bool suppliers\\n ) internal {\\n uint256 j;\\n uint256 holdersLength = holders.length;\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n VToken vToken = vTokens[i];\\n ensureListed(getCorePoolMarket(address(vToken)));\\n if (borrowers) {\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n updateVenusBorrowIndex(address(vToken), borrowIndex);\\n for (j = 0; j < holdersLength; ++j) {\\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\\n }\\n }\\n\\n if (suppliers) {\\n updateVenusSupplyIndex(address(vToken));\\n for (j = 0; j < holdersLength; ++j) {\\n distributeSupplierVenus(address(vToken), holders[j]);\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Returns the XVS vToken address\\n * @return The address of XVS vToken\\n */\\n function getXVSVTokenAddress() external view returns (address) {\\n return xvsVToken;\\n }\\n}\\n\",\"keccak256\":\"0x4f41cd1f11452ef2db24d231998158c0af4a0d71f16e24c527c2096bcd58dbea\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\n\\n/**\\n * @title XVSRewardsHelper\\n * @author Venus\\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\\n */\\ncontract XVSRewardsHelper is FacetBase {\\n /// @notice Emitted when XVS is distributed to a borrower\\n event DistributedBorrowerVenus(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 venusDelta,\\n uint256 venusBorrowIndex\\n );\\n\\n /// @notice Emitted when XVS is distributed to a supplier\\n event DistributedSupplierVenus(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 venusDelta,\\n uint256 venusSupplyIndex\\n );\\n\\n /**\\n * @notice Accrue XVS to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n */\\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\\n if (deltaBlocks != 0 && borrowSpeed != 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \\\"224\\\");\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n borrowState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Accrue XVS to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n */\\n function updateVenusSupplyIndex(address vToken) internal {\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n uint256 supplySpeed = venusSupplySpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\\n if (deltaBlocks != 0 && supplySpeed != 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \\\"224\\\");\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n supplyState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute XVS to\\n */\\n function distributeSupplierVenus(address vToken, address supplier) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 supplyIndex = venusSupplyState[vToken].index;\\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\\n // Update supplier's index to the current index since we are distributing accrued XVS\\n venusSupplierIndex[vToken][supplier] = supplyIndex;\\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n // Multiply of supplierTokens and supplierDelta\\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\\n // Addition of supplierAccrued and supplierDelta\\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute XVS to\\n */\\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 borrowIndex = venusBorrowState[vToken].index;\\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\\n // Update borrowers's index to the current index since we are distributing accrued XVS\\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0xf356db714f7aada286380ee5092b0a3e3163428943cfb5561ded76597e1c0c15\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IFacetBase } from \\\"./IFacetBase.sol\\\";\\n\\ninterface IRewardFacet is IFacetBase {\\n function claimVenus(address holder) external;\\n\\n function claimVenus(address holder, VToken[] calldata vTokens) external;\\n\\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\\n\\n function claimVenusAsCollateral(address holder) external;\\n\\n function _grantXVS(address recipient, uint256 amount) external;\\n\\n function getXVSVTokenAddress() external view returns (address);\\n\\n function claimVenus(\\n address[] calldata holders,\\n VToken[] calldata vTokens,\\n bool borrowers,\\n bool suppliers,\\n bool collateral\\n ) external;\\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xdc0657a78bee600d863de3bc6043afca1b6ecb4cd7c4042dc1857e15981a05b5\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b50612abe8061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610372575f3560e01c80639254f5e5116101d4578063c5f956af11610109578063e0f6123d116100a9578063ededbae611610079578063ededbae6146108bb578063f445d703146108cc578063f851a440146108f9578063fa6331d81461090b575f80fd5b8063e0f6123d14610846578063e37d4b7914610868578063e85a29601461089f578063e8755446146108b2575f80fd5b8063d3270f99116100e4578063d3270f9914610806578063d463654c14610819578063dce1544914610820578063dcfbc0c714610833575f80fd5b8063c5f956af146107cd578063c7ee005e146107e0578063d09c54ba146107f3575f80fd5b8063b2eafc3911610174578063bbb8864a1161014f578063bbb8864a14610767578063bec04f7214610786578063bf32442d1461078f578063c5b4db55146107a0575f80fd5b8063b2eafc39146106e6578063b8324c7c146106f9578063bb82aa5e14610754575f80fd5b80639bb27d62116101af5780639bb27d621461069a578063a657e579146106ad578063a7604b41146106c0578063adcd5fb9146106d3575f80fd5b80639254f5e51461065c57806394b2294b1461066f57806396c9906414610678575f80fd5b806352d84d1e116102aa5780637858524d1161024a5780637fb8e8cd116102255780637fb8e8cd146105fb57806386df31ee146106085780638a7dc1651461061b5780638c1ac18a1461063a575f80fd5b80637858524d146105c25780637d172bd5146105d55780637dc0d1d0146105e8575f80fd5b806370bf66f01161028557806370bf66f014610552578063719f701b14610567578063737690991461057057806376551383146105b0575f80fd5b806352d84d1e1461050d5780635dd3fc9d14610520578063655f07251461053f575f80fd5b8063267822471161031557806341a18d2c116102f057806341a18d2c1461049e578063425fad58146104c85780634a584432146104db5780634d99c776146104fa575f80fd5b8063267822471461045f5780632bc7e29e146104725780634088c73e14610491575f80fd5b80630db4b4e5116103505780630db4b4e5146103db57806310b98338146103e457806321af45691461042157806324a3d6221461044c575f80fd5b806302c3bcbb1461037657806304ef9d58146103a857806308e0225c146103b1575b5f80fd5b610395610384366004612417565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61039560225481565b6103956103bf366004612432565b601360209081525f928352604080842090915290825290205481565b610395601d5481565b6104116103f2366004612432565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161039f565b601e54610434906001600160a01b031681565b6040516001600160a01b03909116815260200161039f565b600a54610434906001600160a01b031681565b600154610434906001600160a01b031681565b610395610480366004612417565b60166020525f908152604090205481565b6018546104119060ff1681565b6103956104ac366004612432565b601260209081525f928352604080842090915290825290205481565b6018546104119062010000900460ff1681565b6103956104e9366004612417565b601f6020525f908152604090205481565b610395610508366004612484565b610914565b61043461051b36600461249e565b610935565b61039561052e366004612417565b602b6020525f908152604090205481565b61039561054d3660046124b5565b61095d565b610565610560366004612683565b610b65565b005b610395601c5481565b61059861057e366004612417565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161039f565b60185461041190610100900460ff1681565b6105656105d0366004612417565b610c14565b601b54610434906001600160a01b031681565b600454610434906001600160a01b031681565b6039546104119060ff1681565b61056561061636600461271b565b610cd3565b610395610629366004612417565b60146020525f908152604090205481565b610411610648366004612417565b602d6020525f908152604090205460ff1681565b601554610434906001600160a01b031681565b61039560075481565b61068b610686366004612768565b610d39565b60405161039f939291906127af565b602554610434906001600160a01b031681565b603754610598906001600160601b031681565b6105656106ce3660046127d8565b610de6565b6105656106e1366004612417565b610e81565b602054610434906001600160a01b031681565b610730610707366004612417565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161039f565b600254610434906001600160a01b031681565b610395610775366004612417565b602a6020525f908152604090205481565b61039560175481565b6033546001600160a01b0316610434565b6107b56a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b03909116815260200161039f565b602154610434906001600160a01b031681565b603154610434906001600160a01b031681565b610565610801366004612802565b610ee6565b602654610434906001600160a01b031681565b6105985f81565b61043461082e3660046127d8565b610ef9565b600354610434906001600160a01b031681565b610411610854366004612417565b60386020525f908152604090205460ff1681565b610730610876366004612417565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6104116108ad366004612886565b610f2d565b61039560055481565b6034546001600160a01b0316610434565b6104116108da366004612432565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610434906001600160a01b031681565b610395601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d8181548110610944575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f61099c6040518060400160405280601d81526020017f7365697a6556656e757328616464726573735b5d2c6164647265737329000000815250610f71565b604080516020808602828101820190935285825285925f92610a339290918991869182918501908490808284375f9201919091525050600d805460408051602080840282018101909252828152945091925090830182828015610a2657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a08575b505050505060018061101e565b5f5b82811015610af8575f878783818110610a5057610a506128b5565b9050602002016020810190610a659190612417565b6001600160a01b0381165f908152601460205260409020549091508015610aab57610a9081856128dd565b6001600160a01b0383165f9081526014602052604081205593505b816001600160a01b03167fa82ad8dba07d5fde98bd3f0ef9b20c6426de9d477bb7647d46e0c7e50c7dc1b282604051610ae691815260200190565b60405180910390a25050600101610a35565b508015610b5a57603354610b16906001600160a01b03168583611176565b836001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e82604051610b5191815260200190565b60405180910390a25b9150505b9392505050565b8451610b738686868661101e565b5f5b81811015610c0b575f878281518110610b9057610b906128b5565b602002602001015190505f610ba8825f805f806111d9565b6001600160a01b0385165f9081526014602052604081208054908290559194509092509050610bd98483858a611286565b90508015610bfc576001600160a01b0384165f9081526014602052604090208190555b50505050806001019050610b75565b50505050505050565b6040805160018082528183019092525f916020808301908036833701905050905081815f81518110610c4857610c486128b5565b60200260200101906001600160a01b031690816001600160a01b031681525050610ccf81600d805480602002602001604051908101604052809291908181526020018280548015610cc057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ca2575b50505050506001806001610b65565b5050565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610d0757610d076128b5565b60200260200101906001600160a01b031690816001600160a01b031681525050610d348183600180610ee6565b505050565b60366020525f9081526040902080548190610d53906128f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7f906128f0565b8015610dca5780601f10610da157610100808354040283529160200191610dca565b820191905f5260205f20905b815481529060010190602001808311610dad57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b610dee611534565b5f610dfb83835f80611286565b90508015610e395760405162461bcd60e51b81526020600482015260066024820152656e6f2078767360d01b60448201526064015b60405180910390fd5b826001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e83604051610e7491815260200190565b60405180910390a2505050565b610ee381600d805480602002602001604051908101604052809291908181526020018280548015610ed957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ebb575b5050505050610cd3565b50565b610ef3848484845f610b65565b50505050565b6008602052815f5260405f208181548110610f12575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610f5757610f57612928565b815260208101919091526040015f205460ff169392505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90610fa3903390859060040161293c565b602060405180830381865afa158015610fbe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe2919061295f565b610ee35760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e30565b835183515f9190825b8181101561116c575f878281518110611042576110426128b5565b6020026020010151905061105d61105882611580565b6115a2565b861561111a575f6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110cf919061297a565b905290506110dd82826115e7565b5f95505b848610156111185761110d828b88815181106110ff576110ff6128b5565b60200260200101518361177d565b8560010195506110e1565b505b85156111635761112981611901565b5f94505b8385101561116357611158818a878151811061114b5761114b6128b5565b6020026020010151611a6d565b84600101945061112d565b50600101611027565b5050505050505050565b6040516001600160a01b038316602482015260448101829052610d3490849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c0b565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e9061121f9030908f908f908f908f908f90600401612991565b606060405180830381865afa15801561123a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061125e91906129ec565b92509250925082601481111561127657611276612928565b9b919a5098509650505050505050565b5f73ef044206db68e40520bfa82d45419d498b4bc7bf6001600160a01b038616148015906112d15750737589dd3355dae848fdbf75044a3495351655cb1a6001600160a01b03861614155b80156112fa57507333df7a7f6d44307e1e5f3b15975b47515e5524c06001600160a01b03861614155b801561132357507324e77e5b74b30b026e9996e4bc3329c881e249686001600160a01b03861614155b61135d5760405162461bcd60e51b815260206004820152600b60248201526a109b1858dadb1a5cdd195960aa1b6044820152606401610e30565b6033546001600160a01b03168415806113da57506040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113d7919061297a565b85115b156113e8578491505061152c565b835f0361140c576114036001600160a01b0382168787611176565b5f91505061152c565b826114445760405162461bcd60e51b815260206004820152600860248201526718985b9adc9d5c1d60c21b6044820152606401610e30565b6034546001600160a01b0390811690611460908316825f611cde565b6114746001600160a01b0383168288611cde565b5f6040516323323e0360e01b81526001600160a01b038981166004830152602482018990528316906323323e03906044016020604051808303815f875af11580156114c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114e5919061297a565b146115265760405162461bcd60e51b815260206004820152601160248201527036b4b73a103132b430b6331032b93937b960791b6044820152606401610e30565b5f925050505b949350505050565b5f546001600160a01b0316331461157e5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e30565b565b5f60095f61158e5f85610914565b81526020019081526020015f209050919050565b805460ff16610ee35760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e30565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611613611df1565b83549091505f906116349063ffffffff80851691600160e01b900416611e2a565b9050801580159061164457508215155b15611753575f6116b3876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611689573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116ad919061297a565b87611e63565b90505f6116c08386611e80565b90505f825f036116de5760405180602001604052805f8152506116e8565b6116e88284611ec1565b604080516020810190915288546001600160e01b03168152909150611731906117119083611f04565b516040805180820190915260038152620c8c8d60ea1b6020820152611f2d565b6001600160e01b0316600160e01b63ffffffff87160217875550611775915050565b80156117755783546001600160e01b0316600160e01b63ffffffff8416021784555b505050505050565b601b546001600160a01b03161561179657611796611f5b565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b039092169081905590801580156117f257506a0c097ce7bc90715b34b9f160241b8210155b1561180857506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061181e8585611e2a565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f9161187791611871918a16906395dd919390602401602060405180830381865afa158015611689573d5f803e3d5ffd5b836120ea565b6001600160a01b0387165f9081526014602052604090205490915061189c9082612111565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161192d611df1565b83549091505f9061194e9063ffffffff80851691600160e01b900416611e2a565b9050801580159061195e57508215155b15611a44575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119c4919061297a565b90505f6119d18386611e80565b90505f825f036119ef5760405180602001604052805f8152506119f9565b6119f98284611ec1565b604080516020810190915288546001600160e01b03168152909150611a22906117119083611f04565b6001600160e01b0316600160e01b63ffffffff87160217875550611a66915050565b8015611a665783546001600160e01b0316600160e01b63ffffffff8416021784555b5050505050565b601b546001600160a01b031615611a8657611a86611f5b565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b03909216908190559080158015611ae257506a0c097ce7bc90715b34b9f160241b8210155b15611af857506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611b0e8585611e2a565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f91611b8291908816906370a0823190602401602060405180830381865afa158015611b5e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611871919061297a565b6001600160a01b0386165f90815260146020526040902054909150611ba79082612111565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f611c5f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121469092919063ffffffff16565b905080515f1480611c7f575080806020019051810190611c7f919061295f565b610d345760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e30565b801580611d565750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611d30573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d54919061297a565b155b611dc15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e30565b6040516001600160a01b038316602482015260448101829052610d3490849063095ea7b360e01b906064016111a2565b5f611e254360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612154565b905090565b5f610b5e8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061217b565b5f610b5e611e7984670de0b6b3a7640000611e80565b83516121a9565b5f610b5e83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506121db565b60408051602081019091525f81526040518060200160405280611efb611ef5866a0c097ce7bc90715b34b9f160241b611e80565b856121a9565b90529392505050565b60408051602081019091525f81526040518060200160405280611efb855f0151855f0151612111565b5f81600160e01b8410611f535760405162461bcd60e51b8152600401610e309190612a17565b509192915050565b601c541580611f6b5750601c5443105b15611f7257565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015611fbc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe0919061297a565b9050805f03611fed575050565b5f80611ffb43601c54611e2a565b90505f61200a601a5483611e80565b905080841061201b5780925061201f565b8392505b601d54831015612030575050505050565b43601c55601b5461204e906001600160a01b03878116911685611176565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156120cd575f80fd5b505af11580156120df573d5f803e3d5ffd5b505050505050505050565b5f6a0c097ce7bc90715b34b9f160241b61210784845f0151611e80565b610b5e9190612a29565b5f610b5e8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612234565b606061152c84845f85612264565b5f816401000000008410611f535760405162461bcd60e51b8152600401610e309190612a17565b5f818484111561219e5760405162461bcd60e51b8152600401610e309190612a17565b5061152c8385612a48565b5f610b5e83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525061233b565b5f8315806121e7575082155b156121f357505f610b5e565b5f6121fe8486612a5b565b90508361220b8683612a29565b14839061222b5760405162461bcd60e51b8152600401610e309190612a17565b50949350505050565b5f8061224084866128dd565b9050828582101561222b5760405162461bcd60e51b8152600401610e309190612a17565b6060824710156122c55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e30565b5f80866001600160a01b031685876040516122e09190612a72565b5f6040518083038185875af1925050503d805f811461231a576040519150601f19603f3d011682016040523d82523d5f602084013e61231f565b606091505b509150915061233087838387612366565b979650505050505050565b5f818361235b5760405162461bcd60e51b8152600401610e309190612a17565b5061152c8385612a29565b606083156123d45782515f036123cd576001600160a01b0385163b6123cd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e30565b508161152c565b61152c83838151156123e95781518083602001fd5b8060405162461bcd60e51b8152600401610e309190612a17565b6001600160a01b0381168114610ee3575f80fd5b5f60208284031215612427575f80fd5b8135610b5e81612403565b5f8060408385031215612443575f80fd5b823561244e81612403565b9150602083013561245e81612403565b809150509250929050565b80356001600160601b038116811461247f575f80fd5b919050565b5f8060408385031215612495575f80fd5b61244e83612469565b5f602082840312156124ae575f80fd5b5035919050565b5f805f604084860312156124c7575f80fd5b833567ffffffffffffffff808211156124de575f80fd5b818601915086601f8301126124f1575f80fd5b8135818111156124ff575f80fd5b8760208260051b8501011115612513575f80fd5b6020928301955093505084013561252981612403565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561257157612571612534565b604052919050565b5f67ffffffffffffffff82111561259257612592612534565b5060051b60200190565b5f82601f8301126125ab575f80fd5b813560206125c06125bb83612579565b612548565b8083825260208201915060208460051b8701019350868411156125e1575f80fd5b602086015b848110156126065780356125f981612403565b83529183019183016125e6565b509695505050505050565b5f82601f830112612620575f80fd5b813560206126306125bb83612579565b8083825260208201915060208460051b870101935086841115612651575f80fd5b602086015b8481101561260657803561266981612403565b8352918301918301612656565b8015158114610ee3575f80fd5b5f805f805f60a08688031215612697575f80fd5b853567ffffffffffffffff808211156126ae575f80fd5b6126ba89838a0161259c565b965060208801359150808211156126cf575f80fd5b506126dc88828901612611565b94505060408601356126ed81612676565b925060608601356126fd81612676565b9150608086013561270d81612676565b809150509295509295909350565b5f806040838503121561272c575f80fd5b823561273781612403565b9150602083013567ffffffffffffffff811115612752575f80fd5b61275e85828601612611565b9150509250929050565b5f60208284031215612778575f80fd5b610b5e82612469565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6127c16060830186612781565b931515602083015250901515604090910152919050565b5f80604083850312156127e9575f80fd5b82356127f481612403565b946020939093013593505050565b5f805f8060808587031215612815575f80fd5b843567ffffffffffffffff8082111561282c575f80fd5b6128388883890161259c565b9550602087013591508082111561284d575f80fd5b5061285a87828801612611565b935050604085013561286b81612676565b9150606085013561287b81612676565b939692955090935050565b5f8060408385031215612897575f80fd5b82356128a281612403565b915060208301356009811061245e575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561092f5761092f6128c9565b600181811c9082168061290457607f821691505b60208210810361292257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040602082018190525f9061152c90830184612781565b5f6020828403121561296f575f80fd5b8151610b5e81612676565b5f6020828403121561298a575f80fd5b5051919050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101600283106129db57634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f606084860312156129fe575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610b5e6020830184612781565b5f82612a4357634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561092f5761092f6128c9565b808202811582820484141761092f5761092f6128c9565b5f82518060208501845e5f92019182525091905056fea264697066735822122017d59e4712f7786caae56c195ab5a337020d4fb0e25480df676cefb75874181464736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b5060043610610372575f3560e01c80639254f5e5116101d4578063c5f956af11610109578063e0f6123d116100a9578063ededbae611610079578063ededbae6146108bb578063f445d703146108cc578063f851a440146108f9578063fa6331d81461090b575f80fd5b8063e0f6123d14610846578063e37d4b7914610868578063e85a29601461089f578063e8755446146108b2575f80fd5b8063d3270f99116100e4578063d3270f9914610806578063d463654c14610819578063dce1544914610820578063dcfbc0c714610833575f80fd5b8063c5f956af146107cd578063c7ee005e146107e0578063d09c54ba146107f3575f80fd5b8063b2eafc3911610174578063bbb8864a1161014f578063bbb8864a14610767578063bec04f7214610786578063bf32442d1461078f578063c5b4db55146107a0575f80fd5b8063b2eafc39146106e6578063b8324c7c146106f9578063bb82aa5e14610754575f80fd5b80639bb27d62116101af5780639bb27d621461069a578063a657e579146106ad578063a7604b41146106c0578063adcd5fb9146106d3575f80fd5b80639254f5e51461065c57806394b2294b1461066f57806396c9906414610678575f80fd5b806352d84d1e116102aa5780637858524d1161024a5780637fb8e8cd116102255780637fb8e8cd146105fb57806386df31ee146106085780638a7dc1651461061b5780638c1ac18a1461063a575f80fd5b80637858524d146105c25780637d172bd5146105d55780637dc0d1d0146105e8575f80fd5b806370bf66f01161028557806370bf66f014610552578063719f701b14610567578063737690991461057057806376551383146105b0575f80fd5b806352d84d1e1461050d5780635dd3fc9d14610520578063655f07251461053f575f80fd5b8063267822471161031557806341a18d2c116102f057806341a18d2c1461049e578063425fad58146104c85780634a584432146104db5780634d99c776146104fa575f80fd5b8063267822471461045f5780632bc7e29e146104725780634088c73e14610491575f80fd5b80630db4b4e5116103505780630db4b4e5146103db57806310b98338146103e457806321af45691461042157806324a3d6221461044c575f80fd5b806302c3bcbb1461037657806304ef9d58146103a857806308e0225c146103b1575b5f80fd5b610395610384366004612417565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b61039560225481565b6103956103bf366004612432565b601360209081525f928352604080842090915290825290205481565b610395601d5481565b6104116103f2366004612432565b602c60209081525f928352604080842090915290825290205460ff1681565b604051901515815260200161039f565b601e54610434906001600160a01b031681565b6040516001600160a01b03909116815260200161039f565b600a54610434906001600160a01b031681565b600154610434906001600160a01b031681565b610395610480366004612417565b60166020525f908152604090205481565b6018546104119060ff1681565b6103956104ac366004612432565b601260209081525f928352604080842090915290825290205481565b6018546104119062010000900460ff1681565b6103956104e9366004612417565b601f6020525f908152604090205481565b610395610508366004612484565b610914565b61043461051b36600461249e565b610935565b61039561052e366004612417565b602b6020525f908152604090205481565b61039561054d3660046124b5565b61095d565b610565610560366004612683565b610b65565b005b610395601c5481565b61059861057e366004612417565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b03909116815260200161039f565b60185461041190610100900460ff1681565b6105656105d0366004612417565b610c14565b601b54610434906001600160a01b031681565b600454610434906001600160a01b031681565b6039546104119060ff1681565b61056561061636600461271b565b610cd3565b610395610629366004612417565b60146020525f908152604090205481565b610411610648366004612417565b602d6020525f908152604090205460ff1681565b601554610434906001600160a01b031681565b61039560075481565b61068b610686366004612768565b610d39565b60405161039f939291906127af565b602554610434906001600160a01b031681565b603754610598906001600160601b031681565b6105656106ce3660046127d8565b610de6565b6105656106e1366004612417565b610e81565b602054610434906001600160a01b031681565b610730610707366004612417565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff90911660208301520161039f565b600254610434906001600160a01b031681565b610395610775366004612417565b602a6020525f908152604090205481565b61039560175481565b6033546001600160a01b0316610434565b6107b56a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b03909116815260200161039f565b602154610434906001600160a01b031681565b603154610434906001600160a01b031681565b610565610801366004612802565b610ee6565b602654610434906001600160a01b031681565b6105985f81565b61043461082e3660046127d8565b610ef9565b600354610434906001600160a01b031681565b610411610854366004612417565b60386020525f908152604090205460ff1681565b610730610876366004612417565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6104116108ad366004612886565b610f2d565b61039560055481565b6034546001600160a01b0316610434565b6104116108da366004612432565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610434906001600160a01b031681565b610395601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d8181548110610944575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f61099c6040518060400160405280601d81526020017f7365697a6556656e757328616464726573735b5d2c6164647265737329000000815250610f71565b604080516020808602828101820190935285825285925f92610a339290918991869182918501908490808284375f9201919091525050600d805460408051602080840282018101909252828152945091925090830182828015610a2657602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a08575b505050505060018061101e565b5f5b82811015610af8575f878783818110610a5057610a506128b5565b9050602002016020810190610a659190612417565b6001600160a01b0381165f908152601460205260409020549091508015610aab57610a9081856128dd565b6001600160a01b0383165f9081526014602052604081205593505b816001600160a01b03167fa82ad8dba07d5fde98bd3f0ef9b20c6426de9d477bb7647d46e0c7e50c7dc1b282604051610ae691815260200190565b60405180910390a25050600101610a35565b508015610b5a57603354610b16906001600160a01b03168583611176565b836001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e82604051610b5191815260200190565b60405180910390a25b9150505b9392505050565b8451610b738686868661101e565b5f5b81811015610c0b575f878281518110610b9057610b906128b5565b602002602001015190505f610ba8825f805f806111d9565b6001600160a01b0385165f9081526014602052604081208054908290559194509092509050610bd98483858a611286565b90508015610bfc576001600160a01b0384165f9081526014602052604090208190555b50505050806001019050610b75565b50505050505050565b6040805160018082528183019092525f916020808301908036833701905050905081815f81518110610c4857610c486128b5565b60200260200101906001600160a01b031690816001600160a01b031681525050610ccf81600d805480602002602001604051908101604052809291908181526020018280548015610cc057602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ca2575b50505050506001806001610b65565b5050565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610d0757610d076128b5565b60200260200101906001600160a01b031690816001600160a01b031681525050610d348183600180610ee6565b505050565b60366020525f9081526040902080548190610d53906128f0565b80601f0160208091040260200160405190810160405280929190818152602001828054610d7f906128f0565b8015610dca5780601f10610da157610100808354040283529160200191610dca565b820191905f5260205f20905b815481529060010190602001808311610dad57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b610dee611534565b5f610dfb83835f80611286565b90508015610e395760405162461bcd60e51b81526020600482015260066024820152656e6f2078767360d01b60448201526064015b60405180910390fd5b826001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e83604051610e7491815260200190565b60405180910390a2505050565b610ee381600d805480602002602001604051908101604052809291908181526020018280548015610ed957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ebb575b5050505050610cd3565b50565b610ef3848484845f610b65565b50505050565b6008602052815f5260405f208181548110610f12575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610f5757610f57612928565b815260208101919091526040015f205460ff169392505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90610fa3903390859060040161293c565b602060405180830381865afa158015610fbe573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe2919061295f565b610ee35760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e30565b835183515f9190825b8181101561116c575f878281518110611042576110426128b5565b6020026020010151905061105d61105882611580565b6115a2565b861561111a575f6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ab573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110cf919061297a565b905290506110dd82826115e7565b5f95505b848610156111185761110d828b88815181106110ff576110ff6128b5565b60200260200101518361177d565b8560010195506110e1565b505b85156111635761112981611901565b5f94505b8385101561116357611158818a878151811061114b5761114b6128b5565b6020026020010151611a6d565b84600101945061112d565b50600101611027565b5050505050505050565b6040516001600160a01b038316602482015260448101829052610d3490849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c0b565b602654604051637bd48c1f60e11b81525f91829182918291829182916001600160a01b039091169063f7a9183e9061121f9030908f908f908f908f908f90600401612991565b606060405180830381865afa15801561123a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061125e91906129ec565b92509250925082601481111561127657611276612928565b9b919a5098509650505050505050565b5f73ef044206db68e40520bfa82d45419d498b4bc7bf6001600160a01b038616148015906112d15750737589dd3355dae848fdbf75044a3495351655cb1a6001600160a01b03861614155b80156112fa57507333df7a7f6d44307e1e5f3b15975b47515e5524c06001600160a01b03861614155b801561132357507324e77e5b74b30b026e9996e4bc3329c881e249686001600160a01b03861614155b61135d5760405162461bcd60e51b815260206004820152600b60248201526a109b1858dadb1a5cdd195960aa1b6044820152606401610e30565b6033546001600160a01b03168415806113da57506040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113b3573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113d7919061297a565b85115b156113e8578491505061152c565b835f0361140c576114036001600160a01b0382168787611176565b5f91505061152c565b826114445760405162461bcd60e51b815260206004820152600860248201526718985b9adc9d5c1d60c21b6044820152606401610e30565b6034546001600160a01b0390811690611460908316825f611cde565b6114746001600160a01b0383168288611cde565b5f6040516323323e0360e01b81526001600160a01b038981166004830152602482018990528316906323323e03906044016020604051808303815f875af11580156114c1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114e5919061297a565b146115265760405162461bcd60e51b815260206004820152601160248201527036b4b73a103132b430b6331032b93937b960791b6044820152606401610e30565b5f925050505b949350505050565b5f546001600160a01b0316331461157e5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e30565b565b5f60095f61158e5f85610914565b81526020019081526020015f209050919050565b805460ff16610ee35760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e30565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611613611df1565b83549091505f906116349063ffffffff80851691600160e01b900416611e2a565b9050801580159061164457508215155b15611753575f6116b3876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa158015611689573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116ad919061297a565b87611e63565b90505f6116c08386611e80565b90505f825f036116de5760405180602001604052805f8152506116e8565b6116e88284611ec1565b604080516020810190915288546001600160e01b03168152909150611731906117119083611f04565b516040805180820190915260038152620c8c8d60ea1b6020820152611f2d565b6001600160e01b0316600160e01b63ffffffff87160217875550611775915050565b80156117755783546001600160e01b0316600160e01b63ffffffff8416021784555b505050505050565b601b546001600160a01b03161561179657611796611f5b565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b039092169081905590801580156117f257506a0c097ce7bc90715b34b9f160241b8210155b1561180857506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061181e8585611e2a565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f9161187791611871918a16906395dd919390602401602060405180830381865afa158015611689573d5f803e3d5ffd5b836120ea565b6001600160a01b0387165f9081526014602052604090205490915061189c9082612111565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161192d611df1565b83549091505f9061194e9063ffffffff80851691600160e01b900416611e2a565b9050801580159061195e57508215155b15611a44575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119a0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119c4919061297a565b90505f6119d18386611e80565b90505f825f036119ef5760405180602001604052805f8152506119f9565b6119f98284611ec1565b604080516020810190915288546001600160e01b03168152909150611a22906117119083611f04565b6001600160e01b0316600160e01b63ffffffff87160217875550611a66915050565b8015611a665783546001600160e01b0316600160e01b63ffffffff8416021784555b5050505050565b601b546001600160a01b031615611a8657611a86611f5b565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b03909216908190559080158015611ae257506a0c097ce7bc90715b34b9f160241b8210155b15611af857506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611b0e8585611e2a565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f91611b8291908816906370a0823190602401602060405180830381865afa158015611b5e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611871919061297a565b6001600160a01b0386165f90815260146020526040902054909150611ba79082612111565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f611c5f826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166121469092919063ffffffff16565b905080515f1480611c7f575080806020019051810190611c7f919061295f565b610d345760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e30565b801580611d565750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611d30573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d54919061297a565b155b611dc15760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e30565b6040516001600160a01b038316602482015260448101829052610d3490849063095ea7b360e01b906064016111a2565b5f611e254360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b815250612154565b905090565b5f610b5e8383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061217b565b5f610b5e611e7984670de0b6b3a7640000611e80565b83516121a9565b5f610b5e83836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506121db565b60408051602081019091525f81526040518060200160405280611efb611ef5866a0c097ce7bc90715b34b9f160241b611e80565b856121a9565b90529392505050565b60408051602081019091525f81526040518060200160405280611efb855f0151855f0151612111565b5f81600160e01b8410611f535760405162461bcd60e51b8152600401610e309190612a17565b509192915050565b601c541580611f6b5750601c5443105b15611f7257565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015611fbc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611fe0919061297a565b9050805f03611fed575050565b5f80611ffb43601c54611e2a565b90505f61200a601a5483611e80565b905080841061201b5780925061201f565b8392505b601d54831015612030575050505050565b43601c55601b5461204e906001600160a01b03878116911685611176565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156120cd575f80fd5b505af11580156120df573d5f803e3d5ffd5b505050505050505050565b5f6a0c097ce7bc90715b34b9f160241b61210784845f0151611e80565b610b5e9190612a29565b5f610b5e8383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250612234565b606061152c84845f85612264565b5f816401000000008410611f535760405162461bcd60e51b8152600401610e309190612a17565b5f818484111561219e5760405162461bcd60e51b8152600401610e309190612a17565b5061152c8385612a48565b5f610b5e83836040518060400160405280600e81526020016d646976696465206279207a65726f60901b81525061233b565b5f8315806121e7575082155b156121f357505f610b5e565b5f6121fe8486612a5b565b90508361220b8683612a29565b14839061222b5760405162461bcd60e51b8152600401610e309190612a17565b50949350505050565b5f8061224084866128dd565b9050828582101561222b5760405162461bcd60e51b8152600401610e309190612a17565b6060824710156122c55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e30565b5f80866001600160a01b031685876040516122e09190612a72565b5f6040518083038185875af1925050503d805f811461231a576040519150601f19603f3d011682016040523d82523d5f602084013e61231f565b606091505b509150915061233087838387612366565b979650505050505050565b5f818361235b5760405162461bcd60e51b8152600401610e309190612a17565b5061152c8385612a29565b606083156123d45782515f036123cd576001600160a01b0385163b6123cd5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e30565b508161152c565b61152c83838151156123e95781518083602001fd5b8060405162461bcd60e51b8152600401610e309190612a17565b6001600160a01b0381168114610ee3575f80fd5b5f60208284031215612427575f80fd5b8135610b5e81612403565b5f8060408385031215612443575f80fd5b823561244e81612403565b9150602083013561245e81612403565b809150509250929050565b80356001600160601b038116811461247f575f80fd5b919050565b5f8060408385031215612495575f80fd5b61244e83612469565b5f602082840312156124ae575f80fd5b5035919050565b5f805f604084860312156124c7575f80fd5b833567ffffffffffffffff808211156124de575f80fd5b818601915086601f8301126124f1575f80fd5b8135818111156124ff575f80fd5b8760208260051b8501011115612513575f80fd5b6020928301955093505084013561252981612403565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561257157612571612534565b604052919050565b5f67ffffffffffffffff82111561259257612592612534565b5060051b60200190565b5f82601f8301126125ab575f80fd5b813560206125c06125bb83612579565b612548565b8083825260208201915060208460051b8701019350868411156125e1575f80fd5b602086015b848110156126065780356125f981612403565b83529183019183016125e6565b509695505050505050565b5f82601f830112612620575f80fd5b813560206126306125bb83612579565b8083825260208201915060208460051b870101935086841115612651575f80fd5b602086015b8481101561260657803561266981612403565b8352918301918301612656565b8015158114610ee3575f80fd5b5f805f805f60a08688031215612697575f80fd5b853567ffffffffffffffff808211156126ae575f80fd5b6126ba89838a0161259c565b965060208801359150808211156126cf575f80fd5b506126dc88828901612611565b94505060408601356126ed81612676565b925060608601356126fd81612676565b9150608086013561270d81612676565b809150509295509295909350565b5f806040838503121561272c575f80fd5b823561273781612403565b9150602083013567ffffffffffffffff811115612752575f80fd5b61275e85828601612611565b9150509250929050565b5f60208284031215612778575f80fd5b610b5e82612469565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6127c16060830186612781565b931515602083015250901515604090910152919050565b5f80604083850312156127e9575f80fd5b82356127f481612403565b946020939093013593505050565b5f805f8060808587031215612815575f80fd5b843567ffffffffffffffff8082111561282c575f80fd5b6128388883890161259c565b9550602087013591508082111561284d575f80fd5b5061285a87828801612611565b935050604085013561286b81612676565b9150606085013561287b81612676565b939692955090935050565b5f8060408385031215612897575f80fd5b82356128a281612403565b915060208301356009811061245e575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561092f5761092f6128c9565b600181811c9082168061290457607f821691505b60208210810361292257634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040602082018190525f9061152c90830184612781565b5f6020828403121561296f575f80fd5b8151610b5e81612676565b5f6020828403121561298a575f80fd5b5051919050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c08101600283106129db57634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f606084860312156129fe575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610b5e6020830184612781565b5f82612a4357634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561092f5761092f6128c9565b808202811582820484141761092f5761092f6128c9565b5f82518060208501845e5f92019182525091905056fea264697066735822122017d59e4712f7786caae56c195ab5a337020d4fb0e25480df676cefb75874181464736f6c63430008190033", + "numDeployments": 8, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusBorrowIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedBorrowerVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"supplier\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusDelta\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"venusSupplyIndex\",\"type\":\"uint256\"}],\"name\":\"DistributedSupplierVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"VenusGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"VenusSeized\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"_grantXVS\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"collateral\",\"type\":\"bool\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"borrowers\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"suppliers\",\"type\":\"bool\"}],\"name\":\"claimVenus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"holder\",\"type\":\"address\"}],\"name\":\"claimVenusAsCollateral\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSVTokenAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"holders\",\"type\":\"address[]\"},{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"seizeVenus\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the methods related to the reward functionality\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_grantXVS(address,uint256)\":{\"details\":\"Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall Note: If there is not enough XVS, we do not perform the transfer all\",\"params\":{\"amount\":\"The amount of XVS to (possibly) transfer\",\"recipient\":\"The address of the recipient to transfer XVS to\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"claimVenus(address)\":{\"params\":{\"holder\":\"The address to claim XVS for\"}},\"claimVenus(address,address[])\":{\"params\":{\"holder\":\"The address to claim XVS for\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenus(address[],address[],bool,bool)\":{\"params\":{\"borrowers\":\"Whether or not to claim XVS earned by borrowing\",\"holders\":\"The addresses to claim XVS for\",\"suppliers\":\"Whether or not to claim XVS earned by supplying\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenus(address[],address[],bool,bool,bool)\":{\"details\":\"The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices. When DBO protection mode is active, a holder with a position that is healthy at spot prices may still show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO.\",\"params\":{\"borrowers\":\"Whether or not to claim XVS earned by borrowing\",\"collateral\":\"Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\",\"holders\":\"The addresses to claim XVS for\",\"suppliers\":\"Whether or not to claim XVS earned by supplying\",\"vTokens\":\"The list of markets to claim XVS in\"}},\"claimVenusAsCollateral(address)\":{\"params\":{\"holder\":\"The address to claim XVS for\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"getXVSVTokenAddress()\":{\"returns\":{\"_0\":\"The address of XVS vToken\"}},\"seizeVenus(address[],address)\":{\"details\":\"Seize XVS tokens from the specified holders and transfer to recipient\",\"params\":{\"holders\":\"Addresses of the XVS holders\",\"recipient\":\"Address of the XVS token recipient\"},\"returns\":{\"_0\":\"The total amount of XVS tokens seized and transferred to recipient\"}}},\"title\":\"RewardFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"DistributedBorrowerVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a borrower\"},\"DistributedSupplierVenus(address,address,uint256,uint256)\":{\"notice\":\"Emitted when XVS is distributed to a supplier\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"VenusGranted(address,uint256)\":{\"notice\":\"Emitted when Venus is granted by admin\"},\"VenusSeized(address,uint256)\":{\"notice\":\"Emitted when XVS are seized for the holder\"}},\"kind\":\"user\",\"methods\":{\"_grantXVS(address,uint256)\":{\"notice\":\"Transfer XVS to the recipient\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"claimVenus(address)\":{\"notice\":\"Claim all the xvs accrued by holder in all markets and VAI\"},\"claimVenus(address,address[])\":{\"notice\":\"Claim all the xvs accrued by holder in the specified markets\"},\"claimVenus(address[],address[],bool,bool)\":{\"notice\":\"Claim all xvs accrued by the holders\"},\"claimVenus(address[],address[],bool,bool,bool)\":{\"notice\":\"Claim all xvs accrued by the holders\"},\"claimVenusAsCollateral(address)\":{\"notice\":\"Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"getXVSVTokenAddress()\":{\"notice\":\"Returns the XVS vToken address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"seizeVenus(address[],address)\":{\"notice\":\"Seize XVS rewards allocated to holders\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract provides the external functions related to all claims and rewards of the protocol\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/RewardFacet.sol\":\"RewardFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/RewardFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { IRewardFacet } from \\\"../interfaces/IRewardFacet.sol\\\";\\nimport { XVSRewardsHelper } from \\\"./XVSRewardsHelper.sol\\\";\\nimport { VBep20Interface } from \\\"../../../Tokens/VTokens/VTokenInterfaces.sol\\\";\\nimport { WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title RewardFacet\\n * @author Venus\\n * @dev This facet contains all the methods related to the reward functionality\\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\\n */\\ncontract RewardFacet is IRewardFacet, XVSRewardsHelper {\\n /// @notice Emitted when Venus is granted by admin\\n event VenusGranted(address indexed recipient, uint256 amount);\\n\\n /// @notice Emitted when XVS are seized for the holder\\n event VenusSeized(address indexed holder, uint256 amount);\\n\\n using SafeERC20 for IERC20;\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in all markets and VAI\\n * @param holder The address to claim XVS for\\n */\\n function claimVenus(address holder) public {\\n return claimVenus(holder, allMarkets);\\n }\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in the specified markets\\n * @param holder The address to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n */\\n function claimVenus(address holder, VToken[] memory vTokens) public {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimVenus(holders, vTokens, true, true);\\n }\\n\\n /**\\n * @notice Claim all xvs accrued by the holders\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n */\\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\\n claimVenus(holders, vTokens, borrowers, suppliers, false);\\n }\\n\\n /**\\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\\n * @param holder The address to claim XVS for\\n */\\n function claimVenusAsCollateral(address holder) external {\\n address[] memory holders = new address[](1);\\n holders[0] = holder;\\n claimVenus(holders, allMarkets, true, true, true);\\n }\\n\\n /**\\n * @notice Transfer XVS to the user with user's shortfall considered\\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\\n * @param user The address of the user to transfer XVS to\\n * @param amount The amount of XVS to (possibly) transfer\\n * @param shortfall The shortfall of the user\\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\\n * @return The amount of XVS which was NOT transferred to the user\\n */\\n function grantXVSInternal(\\n address user,\\n uint256 amount,\\n uint256 shortfall,\\n bool collateral\\n ) internal returns (uint256) {\\n // If the user is blacklisted, they can't get XVS rewards\\n require(\\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\\n \\\"Blacklisted\\\"\\n );\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n if (amount == 0 || amount > xvs_.balanceOf(address(this))) {\\n return amount;\\n }\\n\\n if (shortfall == 0) {\\n xvs_.safeTransfer(user, amount);\\n return 0;\\n }\\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\\n // anything, otherwise, we will transfer the pending xvs as collateral to\\n // vXVS token and mint vXVS for the user\\n //\\n // If mintBehalf failed, don't grant any xvs\\n require(collateral, \\\"bankrupt\\\");\\n\\n address xvsVToken_ = xvsVToken;\\n\\n xvs_.safeApprove(xvsVToken_, 0);\\n xvs_.safeApprove(xvsVToken_, amount);\\n require(VBep20Interface(xvsVToken_).mintBehalf(user, amount) == uint256(Error.NO_ERROR), \\\"mint behalf error\\\");\\n\\n // set venusAccrued[user] to 0\\n return 0;\\n }\\n\\n /*** Venus Distribution Admin ***/\\n\\n /**\\n * @notice Transfer XVS to the recipient\\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\\n * Note: If there is not enough XVS, we do not perform the transfer all\\n * @param recipient The address of the recipient to transfer XVS to\\n * @param amount The amount of XVS to (possibly) transfer\\n */\\n function _grantXVS(address recipient, uint256 amount) external {\\n ensureAdmin();\\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\\n require(amountLeft == 0, \\\"no xvs\\\");\\n emit VenusGranted(recipient, amount);\\n }\\n\\n /**\\n * @dev Seize XVS tokens from the specified holders and transfer to recipient\\n * @notice Seize XVS rewards allocated to holders\\n * @param holders Addresses of the XVS holders\\n * @param recipient Address of the XVS token recipient\\n * @return The total amount of XVS tokens seized and transferred to recipient\\n */\\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256) {\\n ensureAllowed(\\\"seizeVenus(address[],address)\\\");\\n\\n uint256 holdersLength = holders.length;\\n uint256 totalHoldings;\\n\\n updateAndDistributeRewardsInternal(holders, allMarkets, true, true);\\n for (uint256 j; j < holdersLength; ++j) {\\n address holder = holders[j];\\n uint256 userHolding = venusAccrued[holder];\\n\\n if (userHolding != 0) {\\n totalHoldings += userHolding;\\n delete venusAccrued[holder];\\n }\\n\\n emit VenusSeized(holder, userHolding);\\n }\\n\\n if (totalHoldings != 0) {\\n IERC20(xvs).safeTransfer(recipient, totalHoldings);\\n emit VenusGranted(recipient, totalHoldings);\\n }\\n\\n return totalHoldings;\\n }\\n\\n /**\\n * @notice Claim all xvs accrued by the holders\\n * @dev The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices.\\n * When DBO protection mode is active, a holder with a position that is healthy at spot prices may still\\n * show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when\\n * `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO.\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\\n */\\n function claimVenus(\\n address[] memory holders,\\n VToken[] memory vTokens,\\n bool borrowers,\\n bool suppliers,\\n bool collateral\\n ) public {\\n uint256 holdersLength = holders.length;\\n\\n updateAndDistributeRewardsInternal(holders, vTokens, borrowers, suppliers);\\n for (uint256 j; j < holdersLength; ++j) {\\n address holder = holders[j];\\n\\n // If there is a positive shortfall, the XVS reward is accrued,\\n // but won't be granted to this holder\\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n holder,\\n VToken(address(0)),\\n 0,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n\\n uint256 value = venusAccrued[holder];\\n delete venusAccrued[holder];\\n\\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\\n\\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\\n if (returnAmount != 0) {\\n venusAccrued[holder] = returnAmount;\\n }\\n }\\n }\\n\\n /**\\n * @notice Update and distribute tokens\\n * @param holders The addresses to claim XVS for\\n * @param vTokens The list of markets to claim XVS in\\n * @param borrowers Whether or not to claim XVS earned by borrowing\\n * @param suppliers Whether or not to claim XVS earned by supplying\\n */\\n function updateAndDistributeRewardsInternal(\\n address[] memory holders,\\n VToken[] memory vTokens,\\n bool borrowers,\\n bool suppliers\\n ) internal {\\n uint256 j;\\n uint256 holdersLength = holders.length;\\n uint256 vTokensLength = vTokens.length;\\n\\n for (uint256 i; i < vTokensLength; ++i) {\\n VToken vToken = vTokens[i];\\n ensureListed(getCorePoolMarket(address(vToken)));\\n if (borrowers) {\\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\\n updateVenusBorrowIndex(address(vToken), borrowIndex);\\n for (j = 0; j < holdersLength; ++j) {\\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\\n }\\n }\\n\\n if (suppliers) {\\n updateVenusSupplyIndex(address(vToken));\\n for (j = 0; j < holdersLength; ++j) {\\n distributeSupplierVenus(address(vToken), holders[j]);\\n }\\n }\\n }\\n }\\n\\n /**\\n * @notice Returns the XVS vToken address\\n * @return The address of XVS vToken\\n */\\n function getXVSVTokenAddress() external view returns (address) {\\n return xvsVToken;\\n }\\n}\\n\",\"keccak256\":\"0xa8406d304c6fd65150a72a108d6a9ecee8e9a921d01862c76aaa9da6b91fd937\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\n\\n/**\\n * @title XVSRewardsHelper\\n * @author Venus\\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\\n */\\ncontract XVSRewardsHelper is FacetBase {\\n /// @notice Emitted when XVS is distributed to a borrower\\n event DistributedBorrowerVenus(\\n VToken indexed vToken,\\n address indexed borrower,\\n uint256 venusDelta,\\n uint256 venusBorrowIndex\\n );\\n\\n /// @notice Emitted when XVS is distributed to a supplier\\n event DistributedSupplierVenus(\\n VToken indexed vToken,\\n address indexed supplier,\\n uint256 venusDelta,\\n uint256 venusSupplyIndex\\n );\\n\\n /**\\n * @notice Accrue XVS to the market by updating the borrow index\\n * @param vToken The market whose borrow index to update\\n */\\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\\n VenusMarketState storage borrowState = venusBorrowState[vToken];\\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\\n if (deltaBlocks != 0 && borrowSpeed != 0) {\\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \\\"224\\\");\\n borrowState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n borrowState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Accrue XVS to the market by updating the supply index\\n * @param vToken The market whose supply index to update\\n */\\n function updateVenusSupplyIndex(address vToken) internal {\\n VenusMarketState storage supplyState = venusSupplyState[vToken];\\n uint256 supplySpeed = venusSupplySpeeds[vToken];\\n uint32 blockNumber = getBlockNumberAsUint32();\\n\\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\\n if (deltaBlocks != 0 && supplySpeed != 0) {\\n uint256 supplyTokens = VToken(vToken).totalSupply();\\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \\\"224\\\");\\n supplyState.block = blockNumber;\\n } else if (deltaBlocks != 0) {\\n supplyState.block = blockNumber;\\n }\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\\n * @param vToken The market in which the supplier is interacting\\n * @param supplier The address of the supplier to distribute XVS to\\n */\\n function distributeSupplierVenus(address vToken, address supplier) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 supplyIndex = venusSupplyState[vToken].index;\\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\\n // Update supplier's index to the current index since we are distributing accrued XVS\\n venusSupplierIndex[vToken][supplier] = supplyIndex;\\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\\n // Covers the case where users supplied tokens before the market's supply state index was set.\\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\\n // set for the market.\\n supplierIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per vToken accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\\n // Multiply of supplierTokens and supplierDelta\\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\\n // Addition of supplierAccrued and supplierDelta\\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\\n }\\n\\n /**\\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\\n * @param vToken The market in which the borrower is interacting\\n * @param borrower The address of the borrower to distribute XVS to\\n */\\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\\n if (address(vaiVaultAddress) != address(0)) {\\n releaseToVault();\\n }\\n uint256 borrowIndex = venusBorrowState[vToken].index;\\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\\n // Update borrowers's index to the current index since we are distributing accrued XVS\\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\\n // set for the market.\\n borrowerIndex = venusInitialIndex;\\n }\\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\\n }\\n}\\n\",\"keccak256\":\"0xf356db714f7aada286380ee5092b0a3e3163428943cfb5561ded76597e1c0c15\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { IFacetBase } from \\\"./IFacetBase.sol\\\";\\n\\ninterface IRewardFacet is IFacetBase {\\n function claimVenus(address holder) external;\\n\\n function claimVenus(address holder, VToken[] calldata vTokens) external;\\n\\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\\n\\n function claimVenusAsCollateral(address holder) external;\\n\\n function _grantXVS(address recipient, uint256 amount) external;\\n\\n function getXVSVTokenAddress() external view returns (address);\\n\\n function claimVenus(\\n address[] calldata holders,\\n VToken[] calldata vTokens,\\n bool borrowers,\\n bool suppliers,\\n bool collateral\\n ) external;\\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xdc0657a78bee600d863de3bc6043afca1b6ecb4cd7c4042dc1857e15981a05b5\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b50612c148061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061037d575f3560e01c806394b2294b116101d4578063c7ee005e11610109578063e0f6123d116100a9578063ededbae611610079578063ededbae6146108de578063f445d703146108ef578063f851a4401461091c578063fa6331d81461092e575f80fd5b8063e0f6123d14610869578063e37d4b791461088b578063e85a2960146108c2578063e8755446146108d5575f80fd5b8063d463654c116100e4578063d463654c14610824578063d7c46d2d1461082b578063dce1544914610843578063dcfbc0c714610856575f80fd5b8063c7ee005e146107eb578063d09c54ba146107fe578063d3270f9914610811575f80fd5b8063b8324c7c11610174578063bec04f721161014f578063bec04f7214610791578063bf32442d1461079a578063c5b4db55146107ab578063c5f956af146107d8575f80fd5b8063b8324c7c14610704578063bb82aa5e1461075f578063bbb8864a14610772575f80fd5b8063a657e579116101af578063a657e579146106b8578063a7604b41146106cb578063adcd5fb9146106de578063b2eafc39146106f1575f80fd5b806394b2294b1461067a57806396c99064146106835780639bb27d62146106a5575f80fd5b806352d84d1e116102b55780637858524d1161025557806386df31ee1161022557806386df31ee146106135780638a7dc165146106265780638c1ac18a146106455780639254f5e514610667575f80fd5b80637858524d146105cd5780637d172bd5146105e05780637dc0d1d0146105f35780637fb8e8cd14610606575f80fd5b806370bf66f01161029057806370bf66f01461055d578063719f701b14610572578063737690991461057b57806376551383146105bb575f80fd5b806352d84d1e146105185780635dd3fc9d1461052b578063655f07251461054a575f80fd5b8063267822471161032057806341a18d2c116102fb57806341a18d2c146104a9578063425fad58146104d35780634a584432146104e65780634d99c77614610505575f80fd5b8063267822471461046a5780632bc7e29e1461047d5780634088c73e1461049c575f80fd5b80630db4b4e51161035b5780630db4b4e5146103e657806310b98338146103ef57806321af45691461042c57806324a3d62214610457575f80fd5b806302c3bcbb1461038157806304ef9d58146103b357806308e0225c146103bc575b5f80fd5b6103a061038f36600461256d565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103a060225481565b6103a06103ca366004612588565b601360209081525f928352604080842090915290825290205481565b6103a0601d5481565b61041c6103fd366004612588565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103aa565b601e5461043f906001600160a01b031681565b6040516001600160a01b0390911681526020016103aa565b600a5461043f906001600160a01b031681565b60015461043f906001600160a01b031681565b6103a061048b36600461256d565b60166020525f908152604090205481565b60185461041c9060ff1681565b6103a06104b7366004612588565b601260209081525f928352604080842090915290825290205481565b60185461041c9062010000900460ff1681565b6103a06104f436600461256d565b601f6020525f908152604090205481565b6103a06105133660046125da565b610937565b61043f6105263660046125f4565b610958565b6103a061053936600461256d565b602b6020525f908152604090205481565b6103a061055836600461260b565b610980565b61057061056b3660046127d9565b610b88565b005b6103a0601c5481565b6105a361058936600461256d565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103aa565b60185461041c90610100900460ff1681565b6105706105db36600461256d565b610c37565b601b5461043f906001600160a01b031681565b60045461043f906001600160a01b031681565b60395461041c9060ff1681565b610570610621366004612871565b610cf6565b6103a061063436600461256d565b60146020525f908152604090205481565b61041c61065336600461256d565b602d6020525f908152604090205460ff1681565b60155461043f906001600160a01b031681565b6103a060075481565b6106966106913660046128be565b610d5c565b6040516103aa93929190612905565b60255461043f906001600160a01b031681565b6037546105a3906001600160601b031681565b6105706106d936600461292e565b610e09565b6105706106ec36600461256d565b610ea4565b60205461043f906001600160a01b031681565b61073b61071236600461256d565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103aa565b60025461043f906001600160a01b031681565b6103a061078036600461256d565b602a6020525f908152604090205481565b6103a060175481565b6033546001600160a01b031661043f565b6107c06a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020016103aa565b60215461043f906001600160a01b031681565b60315461043f906001600160a01b031681565b61057061080c366004612958565b610f09565b60265461043f906001600160a01b031681565b6105a35f81565b60395461043f9061010090046001600160a01b031681565b61043f61085136600461292e565b610f1c565b60035461043f906001600160a01b031681565b61041c61087736600461256d565b60386020525f908152604090205460ff1681565b61073b61089936600461256d565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61041c6108d03660046129dc565b610f50565b6103a060055481565b6034546001600160a01b031661043f565b61041c6108fd366004612588565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461043f906001600160a01b031681565b6103a0601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d8181548110610967575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f6109bf6040518060400160405280601d81526020017f7365697a6556656e757328616464726573735b5d2c6164647265737329000000815250610f94565b604080516020808602828101820190935285825285925f92610a569290918991869182918501908490808284375f9201919091525050600d805460408051602080840282018101909252828152945091925090830182828015610a4957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a2b575b5050505050600180611041565b5f5b82811015610b1b575f878783818110610a7357610a73612a0b565b9050602002016020810190610a88919061256d565b6001600160a01b0381165f908152601460205260409020549091508015610ace57610ab38185612a33565b6001600160a01b0383165f9081526014602052604081205593505b816001600160a01b03167fa82ad8dba07d5fde98bd3f0ef9b20c6426de9d477bb7647d46e0c7e50c7dc1b282604051610b0991815260200190565b60405180910390a25050600101610a58565b508015610b7d57603354610b39906001600160a01b03168583611199565b836001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e82604051610b7491815260200190565b60405180910390a25b9150505b9392505050565b8451610b9686868686611041565b5f5b81811015610c2e575f878281518110610bb357610bb3612a0b565b602002602001015190505f610bcb825f805f806111fc565b6001600160a01b0385165f9081526014602052604081208054908290559194509092509050610bfc8483858a6112c5565b90508015610c1f576001600160a01b0384165f9081526014602052604090208190555b50505050806001019050610b98565b50505050505050565b6040805160018082528183019092525f916020808301908036833701905050905081815f81518110610c6b57610c6b612a0b565b60200260200101906001600160a01b031690816001600160a01b031681525050610cf281600d805480602002602001604051908101604052809291908181526020018280548015610ce357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610cc5575b50505050506001806001610b88565b5050565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610d2a57610d2a612a0b565b60200260200101906001600160a01b031690816001600160a01b031681525050610d578183600180610f09565b505050565b60366020525f9081526040902080548190610d7690612a46565b80601f0160208091040260200160405190810160405280929190818152602001828054610da290612a46565b8015610ded5780601f10610dc457610100808354040283529160200191610ded565b820191905f5260205f20905b815481529060010190602001808311610dd057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b610e11611573565b5f610e1e83835f806112c5565b90508015610e5c5760405162461bcd60e51b81526020600482015260066024820152656e6f2078767360d01b60448201526064015b60405180910390fd5b826001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e83604051610e9791815260200190565b60405180910390a2505050565b610f0681600d805480602002602001604051908101604052809291908181526020018280548015610efc57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ede575b5050505050610cf6565b50565b610f16848484845f610b88565b50505050565b6008602052815f5260405f208181548110610f35575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610f7a57610f7a612a7e565b815260208101919091526040015f205460ff169392505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90610fc69033908590600401612a92565b602060405180830381865afa158015610fe1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110059190612ab5565b610f065760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e53565b835183515f9190825b8181101561118f575f87828151811061106557611065612a0b565b6020026020010151905061108061107b826115bf565b6115e1565b861561113d575f6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f29190612ad0565b905290506111008282611626565b5f95505b8486101561113b57611130828b888151811061112257611122612a0b565b6020026020010151836117bc565b856001019550611104565b505b85156111865761114c81611940565b5f94505b838510156111865761117b818a878151811061116e5761116e612a0b565b6020026020010151611aac565b846001019450611150565b5060010161104a565b5050505050505050565b6040516001600160a01b038316602482015260448101829052610d5790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c4a565b5f80808084600181111561121257611212612a7e565b036112205761122088611d1d565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e9061125e9030908f908f908f908f908f90600401612ae7565b606060405180830381865afa158015611279573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061129d9190612b42565b9250925092508260148111156112b5576112b5612a7e565b9b919a5098509650505050505050565b5f73ef044206db68e40520bfa82d45419d498b4bc7bf6001600160a01b038616148015906113105750737589dd3355dae848fdbf75044a3495351655cb1a6001600160a01b03861614155b801561133957507333df7a7f6d44307e1e5f3b15975b47515e5524c06001600160a01b03861614155b801561136257507324e77e5b74b30b026e9996e4bc3329c881e249686001600160a01b03861614155b61139c5760405162461bcd60e51b815260206004820152600b60248201526a109b1858dadb1a5cdd195960aa1b6044820152606401610e53565b6033546001600160a01b031684158061141957506040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113f2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114169190612ad0565b85115b15611427578491505061156b565b835f0361144b576114426001600160a01b0382168787611199565b5f91505061156b565b826114835760405162461bcd60e51b815260206004820152600860248201526718985b9adc9d5c1d60c21b6044820152606401610e53565b6034546001600160a01b039081169061149f908316825f611e34565b6114b36001600160a01b0383168288611e34565b5f6040516323323e0360e01b81526001600160a01b038981166004830152602482018990528316906323323e03906044016020604051808303815f875af1158015611500573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115249190612ad0565b146115655760405162461bcd60e51b815260206004820152601160248201527036b4b73a103132b430b6331032b93937b960791b6044820152606401610e53565b5f925050505b949350505050565b5f546001600160a01b031633146115bd5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e53565b565b5f60095f6115cd5f85610937565b81526020019081526020015f209050919050565b805460ff16610f065760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e53565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611652611f47565b83549091505f906116739063ffffffff80851691600160e01b900416611f80565b9050801580159061168357508215155b15611792575f6116f2876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116ec9190612ad0565b87611fb9565b90505f6116ff8386611fd6565b90505f825f0361171d5760405180602001604052805f815250611727565b6117278284612017565b604080516020810190915288546001600160e01b0316815290915061177090611750908361205a565b516040805180820190915260038152620c8c8d60ea1b6020820152612083565b6001600160e01b0316600160e01b63ffffffff871602178755506117b4915050565b80156117b45783546001600160e01b0316600160e01b63ffffffff8416021784555b505050505050565b601b546001600160a01b0316156117d5576117d56120b1565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b0390921690819055908015801561183157506a0c097ce7bc90715b34b9f160241b8210155b1561184757506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061185d8585611f80565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f916118b6916118b0918a16906395dd919390602401602060405180830381865afa1580156116c8573d5f803e3d5ffd5b83612240565b6001600160a01b0387165f908152601460205260409020549091506118db9082612267565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161196c611f47565b83549091505f9061198d9063ffffffff80851691600160e01b900416611f80565b9050801580159061199d57508215155b15611a83575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119df573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a039190612ad0565b90505f611a108386611fd6565b90505f825f03611a2e5760405180602001604052805f815250611a38565b611a388284612017565b604080516020810190915288546001600160e01b03168152909150611a6190611750908361205a565b6001600160e01b0316600160e01b63ffffffff87160217875550611aa5915050565b8015611aa55783546001600160e01b0316600160e01b63ffffffff8416021784555b5050505050565b601b546001600160a01b031615611ac557611ac56120b1565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b03909216908190559080158015611b2157506a0c097ce7bc90715b34b9f160241b8210155b15611b3757506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611b4d8585611f80565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f91611bc191908816906370a0823190602401602060405180830381865afa158015611b9d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b09190612ad0565b6001600160a01b0386165f90815260146020526040902054909150611be69082612267565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f611c9e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661229c9092919063ffffffff16565b905080515f1480611cbe575080806020019051810190611cbe9190612ab5565b610d575760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e53565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015611d9357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611d75575b505083519394505f925050505b81811015611aa557836001600160a01b031663a9c3cab1848381518110611dc957611dc9612a0b565b60200260200101516040518263ffffffff1660e01b8152600401611dfc91906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015611e13575f80fd5b505af1158015611e25573d5f803e3d5ffd5b50505050806001019050611da0565b801580611eac5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611e86573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eaa9190612ad0565b155b611f175760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e53565b6040516001600160a01b038316602482015260448101829052610d5790849063095ea7b360e01b906064016111c5565b5f611f7b4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b8152506122aa565b905090565b5f610b818383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b8152506122d1565b5f610b81611fcf84670de0b6b3a7640000611fd6565b83516122ff565b5f610b8183836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612331565b60408051602081019091525f8152604051806020016040528061205161204b866a0c097ce7bc90715b34b9f160241b611fd6565b856122ff565b90529392505050565b60408051602081019091525f81526040518060200160405280612051855f0151855f0151612267565b5f81600160e01b84106120a95760405162461bcd60e51b8152600401610e539190612b6d565b509192915050565b601c5415806120c15750601c5443105b156120c857565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015612112573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121369190612ad0565b9050805f03612143575050565b5f8061215143601c54611f80565b90505f612160601a5483611fd6565b905080841061217157809250612175565b8392505b601d54831015612186575050505050565b43601c55601b546121a4906001600160a01b03878116911685611199565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612223575f80fd5b505af1158015612235573d5f803e3d5ffd5b505050505050505050565b5f6a0c097ce7bc90715b34b9f160241b61225d84845f0151611fd6565b610b819190612b7f565b5f610b818383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b81525061238a565b606061156b84845f856123ba565b5f8164010000000084106120a95760405162461bcd60e51b8152600401610e539190612b6d565b5f81848411156122f45760405162461bcd60e51b8152600401610e539190612b6d565b5061156b8385612b9e565b5f610b8183836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612491565b5f83158061233d575082155b1561234957505f610b81565b5f6123548486612bb1565b9050836123618683612b7f565b1483906123815760405162461bcd60e51b8152600401610e539190612b6d565b50949350505050565b5f806123968486612a33565b905082858210156123815760405162461bcd60e51b8152600401610e539190612b6d565b60608247101561241b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e53565b5f80866001600160a01b031685876040516124369190612bc8565b5f6040518083038185875af1925050503d805f8114612470576040519150601f19603f3d011682016040523d82523d5f602084013e612475565b606091505b5091509150612486878383876124bc565b979650505050505050565b5f81836124b15760405162461bcd60e51b8152600401610e539190612b6d565b5061156b8385612b7f565b6060831561252a5782515f03612523576001600160a01b0385163b6125235760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e53565b508161156b565b61156b838381511561253f5781518083602001fd5b8060405162461bcd60e51b8152600401610e539190612b6d565b6001600160a01b0381168114610f06575f80fd5b5f6020828403121561257d575f80fd5b8135610b8181612559565b5f8060408385031215612599575f80fd5b82356125a481612559565b915060208301356125b481612559565b809150509250929050565b80356001600160601b03811681146125d5575f80fd5b919050565b5f80604083850312156125eb575f80fd5b6125a4836125bf565b5f60208284031215612604575f80fd5b5035919050565b5f805f6040848603121561261d575f80fd5b833567ffffffffffffffff80821115612634575f80fd5b818601915086601f830112612647575f80fd5b813581811115612655575f80fd5b8760208260051b8501011115612669575f80fd5b6020928301955093505084013561267f81612559565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156126c7576126c761268a565b604052919050565b5f67ffffffffffffffff8211156126e8576126e861268a565b5060051b60200190565b5f82601f830112612701575f80fd5b81356020612716612711836126cf565b61269e565b8083825260208201915060208460051b870101935086841115612737575f80fd5b602086015b8481101561275c57803561274f81612559565b835291830191830161273c565b509695505050505050565b5f82601f830112612776575f80fd5b81356020612786612711836126cf565b8083825260208201915060208460051b8701019350868411156127a7575f80fd5b602086015b8481101561275c5780356127bf81612559565b83529183019183016127ac565b8015158114610f06575f80fd5b5f805f805f60a086880312156127ed575f80fd5b853567ffffffffffffffff80821115612804575f80fd5b61281089838a016126f2565b96506020880135915080821115612825575f80fd5b5061283288828901612767565b9450506040860135612843816127cc565b92506060860135612853816127cc565b91506080860135612863816127cc565b809150509295509295909350565b5f8060408385031215612882575f80fd5b823561288d81612559565b9150602083013567ffffffffffffffff8111156128a8575f80fd5b6128b485828601612767565b9150509250929050565b5f602082840312156128ce575f80fd5b610b81826125bf565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61291760608301866128d7565b931515602083015250901515604090910152919050565b5f806040838503121561293f575f80fd5b823561294a81612559565b946020939093013593505050565b5f805f806080858703121561296b575f80fd5b843567ffffffffffffffff80821115612982575f80fd5b61298e888389016126f2565b955060208701359150808211156129a3575f80fd5b506129b087828801612767565b93505060408501356129c1816127cc565b915060608501356129d1816127cc565b939692955090935050565b5f80604083850312156129ed575f80fd5b82356129f881612559565b91506020830135600981106125b4575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561095257610952612a1f565b600181811c90821680612a5a57607f821691505b602082108103612a7857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040602082018190525f9061156b908301846128d7565b5f60208284031215612ac5575f80fd5b8151610b81816127cc565b5f60208284031215612ae0575f80fd5b5051919050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c0810160028310612b3157634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f60608486031215612b54575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610b8160208301846128d7565b5f82612b9957634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561095257610952612a1f565b808202811582820484141761095257610952612a1f565b5f82518060208501845e5f92019182525091905056fea2646970667358221220e5af138c4b32a4b05553fe719a20c07fbf9cf3e5462e42ca2f7ecb23c592eb6764736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061037d575f3560e01c806394b2294b116101d4578063c7ee005e11610109578063e0f6123d116100a9578063ededbae611610079578063ededbae6146108de578063f445d703146108ef578063f851a4401461091c578063fa6331d81461092e575f80fd5b8063e0f6123d14610869578063e37d4b791461088b578063e85a2960146108c2578063e8755446146108d5575f80fd5b8063d463654c116100e4578063d463654c14610824578063d7c46d2d1461082b578063dce1544914610843578063dcfbc0c714610856575f80fd5b8063c7ee005e146107eb578063d09c54ba146107fe578063d3270f9914610811575f80fd5b8063b8324c7c11610174578063bec04f721161014f578063bec04f7214610791578063bf32442d1461079a578063c5b4db55146107ab578063c5f956af146107d8575f80fd5b8063b8324c7c14610704578063bb82aa5e1461075f578063bbb8864a14610772575f80fd5b8063a657e579116101af578063a657e579146106b8578063a7604b41146106cb578063adcd5fb9146106de578063b2eafc39146106f1575f80fd5b806394b2294b1461067a57806396c99064146106835780639bb27d62146106a5575f80fd5b806352d84d1e116102b55780637858524d1161025557806386df31ee1161022557806386df31ee146106135780638a7dc165146106265780638c1ac18a146106455780639254f5e514610667575f80fd5b80637858524d146105cd5780637d172bd5146105e05780637dc0d1d0146105f35780637fb8e8cd14610606575f80fd5b806370bf66f01161029057806370bf66f01461055d578063719f701b14610572578063737690991461057b57806376551383146105bb575f80fd5b806352d84d1e146105185780635dd3fc9d1461052b578063655f07251461054a575f80fd5b8063267822471161032057806341a18d2c116102fb57806341a18d2c146104a9578063425fad58146104d35780634a584432146104e65780634d99c77614610505575f80fd5b8063267822471461046a5780632bc7e29e1461047d5780634088c73e1461049c575f80fd5b80630db4b4e51161035b5780630db4b4e5146103e657806310b98338146103ef57806321af45691461042c57806324a3d62214610457575f80fd5b806302c3bcbb1461038157806304ef9d58146103b357806308e0225c146103bc575b5f80fd5b6103a061038f36600461256d565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103a060225481565b6103a06103ca366004612588565b601360209081525f928352604080842090915290825290205481565b6103a0601d5481565b61041c6103fd366004612588565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103aa565b601e5461043f906001600160a01b031681565b6040516001600160a01b0390911681526020016103aa565b600a5461043f906001600160a01b031681565b60015461043f906001600160a01b031681565b6103a061048b36600461256d565b60166020525f908152604090205481565b60185461041c9060ff1681565b6103a06104b7366004612588565b601260209081525f928352604080842090915290825290205481565b60185461041c9062010000900460ff1681565b6103a06104f436600461256d565b601f6020525f908152604090205481565b6103a06105133660046125da565b610937565b61043f6105263660046125f4565b610958565b6103a061053936600461256d565b602b6020525f908152604090205481565b6103a061055836600461260b565b610980565b61057061056b3660046127d9565b610b88565b005b6103a0601c5481565b6105a361058936600461256d565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103aa565b60185461041c90610100900460ff1681565b6105706105db36600461256d565b610c37565b601b5461043f906001600160a01b031681565b60045461043f906001600160a01b031681565b60395461041c9060ff1681565b610570610621366004612871565b610cf6565b6103a061063436600461256d565b60146020525f908152604090205481565b61041c61065336600461256d565b602d6020525f908152604090205460ff1681565b60155461043f906001600160a01b031681565b6103a060075481565b6106966106913660046128be565b610d5c565b6040516103aa93929190612905565b60255461043f906001600160a01b031681565b6037546105a3906001600160601b031681565b6105706106d936600461292e565b610e09565b6105706106ec36600461256d565b610ea4565b60205461043f906001600160a01b031681565b61073b61071236600461256d565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103aa565b60025461043f906001600160a01b031681565b6103a061078036600461256d565b602a6020525f908152604090205481565b6103a060175481565b6033546001600160a01b031661043f565b6107c06a0c097ce7bc90715b34b9f160241b81565b6040516001600160e01b0390911681526020016103aa565b60215461043f906001600160a01b031681565b60315461043f906001600160a01b031681565b61057061080c366004612958565b610f09565b60265461043f906001600160a01b031681565b6105a35f81565b60395461043f9061010090046001600160a01b031681565b61043f61085136600461292e565b610f1c565b60035461043f906001600160a01b031681565b61041c61087736600461256d565b60386020525f908152604090205460ff1681565b61073b61089936600461256d565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61041c6108d03660046129dc565b610f50565b6103a060055481565b6034546001600160a01b031661043f565b61041c6108fd366004612588565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461043f906001600160a01b031681565b6103a0601a5481565b6001600160a01b031960a083901b166001600160a01b038216175b92915050565b600d8181548110610967575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f6109bf6040518060400160405280601d81526020017f7365697a6556656e757328616464726573735b5d2c6164647265737329000000815250610f94565b604080516020808602828101820190935285825285925f92610a569290918991869182918501908490808284375f9201919091525050600d805460408051602080840282018101909252828152945091925090830182828015610a4957602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610a2b575b5050505050600180611041565b5f5b82811015610b1b575f878783818110610a7357610a73612a0b565b9050602002016020810190610a88919061256d565b6001600160a01b0381165f908152601460205260409020549091508015610ace57610ab38185612a33565b6001600160a01b0383165f9081526014602052604081205593505b816001600160a01b03167fa82ad8dba07d5fde98bd3f0ef9b20c6426de9d477bb7647d46e0c7e50c7dc1b282604051610b0991815260200190565b60405180910390a25050600101610a58565b508015610b7d57603354610b39906001600160a01b03168583611199565b836001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e82604051610b7491815260200190565b60405180910390a25b9150505b9392505050565b8451610b9686868686611041565b5f5b81811015610c2e575f878281518110610bb357610bb3612a0b565b602002602001015190505f610bcb825f805f806111fc565b6001600160a01b0385165f9081526014602052604081208054908290559194509092509050610bfc8483858a6112c5565b90508015610c1f576001600160a01b0384165f9081526014602052604090208190555b50505050806001019050610b98565b50505050505050565b6040805160018082528183019092525f916020808301908036833701905050905081815f81518110610c6b57610c6b612a0b565b60200260200101906001600160a01b031690816001600160a01b031681525050610cf281600d805480602002602001604051908101604052809291908181526020018280548015610ce357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610cc5575b50505050506001806001610b88565b5050565b6040805160018082528183019092525f916020808301908036833701905050905082815f81518110610d2a57610d2a612a0b565b60200260200101906001600160a01b031690816001600160a01b031681525050610d578183600180610f09565b505050565b60366020525f9081526040902080548190610d7690612a46565b80601f0160208091040260200160405190810160405280929190818152602001828054610da290612a46565b8015610ded5780601f10610dc457610100808354040283529160200191610ded565b820191905f5260205f20905b815481529060010190602001808311610dd057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b610e11611573565b5f610e1e83835f806112c5565b90508015610e5c5760405162461bcd60e51b81526020600482015260066024820152656e6f2078767360d01b60448201526064015b60405180910390fd5b826001600160a01b03167fd7fe674cac9eee3998fe3cbd7a6f93c3bc70509d97ec1550a59364be6438147e83604051610e9791815260200190565b60405180910390a2505050565b610f0681600d805480602002602001604051908101604052809291908181526020018280548015610efc57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610ede575b5050505050610cf6565b50565b610f16848484845f610b88565b50505050565b6008602052815f5260405f208181548110610f35575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115610f7a57610f7a612a7e565b815260208101919091526040015f205460ff169392505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90610fc69033908590600401612a92565b602060405180830381865afa158015610fe1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110059190612ab5565b610f065760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e53565b835183515f9190825b8181101561118f575f87828151811061106557611065612a0b565b6020026020010151905061108061107b826115bf565b6115e1565b861561113d575f6040518060200160405280836001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156110ce573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110f29190612ad0565b905290506111008282611626565b5f95505b8486101561113b57611130828b888151811061112257611122612a0b565b6020026020010151836117bc565b856001019550611104565b505b85156111865761114c81611940565b5f94505b838510156111865761117b818a878151811061116e5761116e612a0b565b6020026020010151611aac565b846001019450611150565b5060010161104a565b5050505050505050565b6040516001600160a01b038316602482015260448101829052610d5790849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611c4a565b5f80808084600181111561121257611212612a7e565b036112205761122088611d1d565b602654604051637bd48c1f60e11b81525f91829182916001600160a01b03169063f7a9183e9061125e9030908f908f908f908f908f90600401612ae7565b606060405180830381865afa158015611279573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061129d9190612b42565b9250925092508260148111156112b5576112b5612a7e565b9b919a5098509650505050505050565b5f73ef044206db68e40520bfa82d45419d498b4bc7bf6001600160a01b038616148015906113105750737589dd3355dae848fdbf75044a3495351655cb1a6001600160a01b03861614155b801561133957507333df7a7f6d44307e1e5f3b15975b47515e5524c06001600160a01b03861614155b801561136257507324e77e5b74b30b026e9996e4bc3329c881e249686001600160a01b03861614155b61139c5760405162461bcd60e51b815260206004820152600b60248201526a109b1858dadb1a5cdd195960aa1b6044820152606401610e53565b6033546001600160a01b031684158061141957506040516370a0823160e01b81523060048201526001600160a01b038216906370a0823190602401602060405180830381865afa1580156113f2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114169190612ad0565b85115b15611427578491505061156b565b835f0361144b576114426001600160a01b0382168787611199565b5f91505061156b565b826114835760405162461bcd60e51b815260206004820152600860248201526718985b9adc9d5c1d60c21b6044820152606401610e53565b6034546001600160a01b039081169061149f908316825f611e34565b6114b36001600160a01b0383168288611e34565b5f6040516323323e0360e01b81526001600160a01b038981166004830152602482018990528316906323323e03906044016020604051808303815f875af1158015611500573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115249190612ad0565b146115655760405162461bcd60e51b815260206004820152601160248201527036b4b73a103132b430b6331032b93937b960791b6044820152606401610e53565b5f925050505b949350505050565b5f546001600160a01b031633146115bd5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e53565b565b5f60095f6115cd5f85610937565b81526020019081526020015f209050919050565b805460ff16610f065760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e53565b6001600160a01b0382165f908152601160209081526040808320602a9092528220549091611652611f47565b83549091505f906116739063ffffffff80851691600160e01b900416611f80565b9050801580159061168357508215155b15611792575f6116f2876001600160a01b03166347bd37186040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116c8573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116ec9190612ad0565b87611fb9565b90505f6116ff8386611fd6565b90505f825f0361171d5760405180602001604052805f815250611727565b6117278284612017565b604080516020810190915288546001600160e01b0316815290915061177090611750908361205a565b516040805180820190915260038152620c8c8d60ea1b6020820152612083565b6001600160e01b0316600160e01b63ffffffff871602178755506117b4915050565b80156117b45783546001600160e01b0316600160e01b63ffffffff8416021784555b505050505050565b601b546001600160a01b0316156117d5576117d56120b1565b6001600160a01b038381165f9081526011602090815260408083205460138352818420948716845293909152902080546001600160e01b0390921690819055908015801561183157506a0c097ce7bc90715b34b9f160241b8210155b1561184757506a0c097ce7bc90715b34b9f160241b5b5f604051806020016040528061185d8585611f80565b90526040516395dd919360e01b81526001600160a01b0387811660048301529192505f916118b6916118b0918a16906395dd919390602401602060405180830381865afa1580156116c8573d5f803e3d5ffd5b83612240565b6001600160a01b0387165f908152601460205260409020549091506118db9082612267565b6001600160a01b038781165f818152601460209081526040918290209490945580518581529384018890529092918a16917f837bdc11fca9f17ce44167944475225a205279b17e88c791c3b1f66f354668fb910160405180910390a350505050505050565b6001600160a01b0381165f908152601060209081526040808320602b909252822054909161196c611f47565b83549091505f9061198d9063ffffffff80851691600160e01b900416611f80565b9050801580159061199d57508215155b15611a83575f856001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119df573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611a039190612ad0565b90505f611a108386611fd6565b90505f825f03611a2e5760405180602001604052805f815250611a38565b611a388284612017565b604080516020810190915288546001600160e01b03168152909150611a6190611750908361205a565b6001600160e01b0316600160e01b63ffffffff87160217875550611aa5915050565b8015611aa55783546001600160e01b0316600160e01b63ffffffff8416021784555b5050505050565b601b546001600160a01b031615611ac557611ac56120b1565b6001600160a01b038281165f9081526010602090815260408083205460128352818420948616845293909152902080546001600160e01b03909216908190559080158015611b2157506a0c097ce7bc90715b34b9f160241b8210155b15611b3757506a0c097ce7bc90715b34b9f160241b5b5f6040518060200160405280611b4d8585611f80565b90526040516370a0823160e01b81526001600160a01b0386811660048301529192505f91611bc191908816906370a0823190602401602060405180830381865afa158015611b9d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118b09190612ad0565b6001600160a01b0386165f90815260146020526040902054909150611be69082612267565b6001600160a01b038681165f818152601460209081526040918290209490945580518581529384018890529092918916917ffa9d964d891991c113b49e3db1932abd6c67263d387119707aafdd6c4010a3a9910160405180910390a3505050505050565b5f611c9e826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661229c9092919063ffffffff16565b905080515f1480611cbe575080806020019051810190611cbe9190612ab5565b610d575760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e53565b6039546001600160a01b038281165f908152600860209081526040808320805482518185028101850190935280835261010090960490941694929390929091830182828015611d9357602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311611d75575b505083519394505f925050505b81811015611aa557836001600160a01b031663a9c3cab1848381518110611dc957611dc9612a0b565b60200260200101516040518263ffffffff1660e01b8152600401611dfc91906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015611e13575f80fd5b505af1158015611e25573d5f803e3d5ffd5b50505050806001019050611da0565b801580611eac5750604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284169063dd62ed3e90604401602060405180830381865afa158015611e86573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611eaa9190612ad0565b155b611f175760405162461bcd60e51b815260206004820152603660248201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60448201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b6064820152608401610e53565b6040516001600160a01b038316602482015260448101829052610d5790849063095ea7b360e01b906064016111c5565b5f611f7b4360405180604001604052806011815260200170626c6f636b2023203e203332206269747360781b8152506122aa565b905090565b5f610b818383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b8152506122d1565b5f610b81611fcf84670de0b6b3a7640000611fd6565b83516122ff565b5f610b8183836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612331565b60408051602081019091525f8152604051806020016040528061205161204b866a0c097ce7bc90715b34b9f160241b611fd6565b856122ff565b90529392505050565b60408051602081019091525f81526040518060200160405280612051855f0151855f0151612267565b5f81600160e01b84106120a95760405162461bcd60e51b8152600401610e539190612b6d565b509192915050565b601c5415806120c15750601c5443105b156120c857565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa158015612112573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906121369190612ad0565b9050805f03612143575050565b5f8061215143601c54611f80565b90505f612160601a5483611fd6565b905080841061217157809250612175565b8392505b601d54831015612186575050505050565b43601c55601b546121a4906001600160a01b03878116911685611199565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b158015612223575f80fd5b505af1158015612235573d5f803e3d5ffd5b505050505050505050565b5f6a0c097ce7bc90715b34b9f160241b61225d84845f0151611fd6565b610b819190612b7f565b5f610b818383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b81525061238a565b606061156b84845f856123ba565b5f8164010000000084106120a95760405162461bcd60e51b8152600401610e539190612b6d565b5f81848411156122f45760405162461bcd60e51b8152600401610e539190612b6d565b5061156b8385612b9e565b5f610b8183836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250612491565b5f83158061233d575082155b1561234957505f610b81565b5f6123548486612bb1565b9050836123618683612b7f565b1483906123815760405162461bcd60e51b8152600401610e539190612b6d565b50949350505050565b5f806123968486612a33565b905082858210156123815760405162461bcd60e51b8152600401610e539190612b6d565b60608247101561241b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610e53565b5f80866001600160a01b031685876040516124369190612bc8565b5f6040518083038185875af1925050503d805f8114612470576040519150601f19603f3d011682016040523d82523d5f602084013e612475565b606091505b5091509150612486878383876124bc565b979650505050505050565b5f81836124b15760405162461bcd60e51b8152600401610e539190612b6d565b5061156b8385612b7f565b6060831561252a5782515f03612523576001600160a01b0385163b6125235760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e53565b508161156b565b61156b838381511561253f5781518083602001fd5b8060405162461bcd60e51b8152600401610e539190612b6d565b6001600160a01b0381168114610f06575f80fd5b5f6020828403121561257d575f80fd5b8135610b8181612559565b5f8060408385031215612599575f80fd5b82356125a481612559565b915060208301356125b481612559565b809150509250929050565b80356001600160601b03811681146125d5575f80fd5b919050565b5f80604083850312156125eb575f80fd5b6125a4836125bf565b5f60208284031215612604575f80fd5b5035919050565b5f805f6040848603121561261d575f80fd5b833567ffffffffffffffff80821115612634575f80fd5b818601915086601f830112612647575f80fd5b813581811115612655575f80fd5b8760208260051b8501011115612669575f80fd5b6020928301955093505084013561267f81612559565b809150509250925092565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff811182821017156126c7576126c761268a565b604052919050565b5f67ffffffffffffffff8211156126e8576126e861268a565b5060051b60200190565b5f82601f830112612701575f80fd5b81356020612716612711836126cf565b61269e565b8083825260208201915060208460051b870101935086841115612737575f80fd5b602086015b8481101561275c57803561274f81612559565b835291830191830161273c565b509695505050505050565b5f82601f830112612776575f80fd5b81356020612786612711836126cf565b8083825260208201915060208460051b8701019350868411156127a7575f80fd5b602086015b8481101561275c5780356127bf81612559565b83529183019183016127ac565b8015158114610f06575f80fd5b5f805f805f60a086880312156127ed575f80fd5b853567ffffffffffffffff80821115612804575f80fd5b61281089838a016126f2565b96506020880135915080821115612825575f80fd5b5061283288828901612767565b9450506040860135612843816127cc565b92506060860135612853816127cc565b91506080860135612863816127cc565b809150509295509295909350565b5f8060408385031215612882575f80fd5b823561288d81612559565b9150602083013567ffffffffffffffff8111156128a8575f80fd5b6128b485828601612767565b9150509250929050565b5f602082840312156128ce575f80fd5b610b81826125bf565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f61291760608301866128d7565b931515602083015250901515604090910152919050565b5f806040838503121561293f575f80fd5b823561294a81612559565b946020939093013593505050565b5f805f806080858703121561296b575f80fd5b843567ffffffffffffffff80821115612982575f80fd5b61298e888389016126f2565b955060208701359150808211156129a3575f80fd5b506129b087828801612767565b93505060408501356129c1816127cc565b915060608501356129d1816127cc565b939692955090935050565b5f80604083850312156129ed575f80fd5b82356129f881612559565b91506020830135600981106125b4575f80fd5b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8082018082111561095257610952612a1f565b600181811c90821680612a5a57607f821691505b602082108103612a7857634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b6001600160a01b03831681526040602082018190525f9061156b908301846128d7565b5f60208284031215612ac5575f80fd5b8151610b81816127cc565b5f60208284031215612ae0575f80fd5b5051919050565b6001600160a01b038781168252868116602083015285166040820152606081018490526080810183905260c0810160028310612b3157634e487b7160e01b5f52602160045260245ffd5b8260a0830152979650505050505050565b5f805f60608486031215612b54575f80fd5b8351925060208401519150604084015190509250925092565b602081525f610b8160208301846128d7565b5f82612b9957634e487b7160e01b5f52601260045260245ffd5b500490565b8181038181111561095257610952612a1f565b808202811582820484141761095257610952612a1f565b5f82518060208501845e5f92019182525091905056fea2646970667358221220e5af138c4b32a4b05553fe719a20c07fbf9cf3e5462e42ca2f7ecb23c592eb6764736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This facet contains all the methods related to the reward functionality", @@ -1411,6 +1424,7 @@ } }, "claimVenus(address[],address[],bool,bool,bool)": { + "details": "The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices. When DBO protection mode is active, a holder with a position that is healthy at spot prices may still show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO.", "params": { "borrowers": "Whether or not to claim XVS earned by borrowing", "collateral": "Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall", @@ -1621,6 +1635,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "flashLoanPaused()": { "notice": "Whether flash loans are paused system-wide" }, @@ -1730,7 +1747,7 @@ "storageLayout": { "storage": [ { - "astId": 1677, + "astId": 9780, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "admin", "offset": 0, @@ -1738,7 +1755,7 @@ "type": "t_address" }, { - "astId": 1680, + "astId": 9783, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "pendingAdmin", "offset": 0, @@ -1746,7 +1763,7 @@ "type": "t_address" }, { - "astId": 1683, + "astId": 9786, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "comptrollerImplementation", "offset": 0, @@ -1754,7 +1771,7 @@ "type": "t_address" }, { - "astId": 1686, + "astId": 9789, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -1762,15 +1779,15 @@ "type": "t_address" }, { - "astId": 1693, + "astId": 9796, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)992" + "type": "t_contract(ResilientOracleInterface)8467" }, { - "astId": 1696, + "astId": 9799, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "closeFactorMantissa", "offset": 0, @@ -1778,7 +1795,7 @@ "type": "t_uint256" }, { - "astId": 1699, + "astId": 9802, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -1786,7 +1803,7 @@ "type": "t_uint256" }, { - "astId": 1702, + "astId": 9805, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "maxAssets", "offset": 0, @@ -1794,23 +1811,23 @@ "type": "t_uint256" }, { - "astId": 1709, + "astId": 9812, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)" }, { - "astId": 1743, + "astId": 9846, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)" }, { - "astId": 1746, + "astId": 9849, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "pauseGuardian", "offset": 0, @@ -1818,7 +1835,7 @@ "type": "t_address" }, { - "astId": 1749, + "astId": 9852, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -1826,7 +1843,7 @@ "type": "t_bool" }, { - "astId": 1752, + "astId": 9855, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -1834,7 +1851,7 @@ "type": "t_bool" }, { - "astId": 1755, + "astId": 9858, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "transferGuardianPaused", "offset": 22, @@ -1842,7 +1859,7 @@ "type": "t_bool" }, { - "astId": 1758, + "astId": 9861, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -1850,7 +1867,7 @@ "type": "t_bool" }, { - "astId": 1763, + "astId": 9866, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "mintGuardianPaused", "offset": 0, @@ -1858,7 +1875,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1768, + "astId": 9871, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -1866,15 +1883,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1780, + "astId": 9883, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)32634)dyn_storage" + "type": "t_array(t_contract(VToken)58633)dyn_storage" }, { - "astId": 1783, + "astId": 9886, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusRate", "offset": 0, @@ -1882,7 +1899,7 @@ "type": "t_uint256" }, { - "astId": 1788, + "astId": 9891, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusSpeeds", "offset": 0, @@ -1890,23 +1907,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1794, + "astId": 9897, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1800, + "astId": 9903, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1807, + "astId": 9910, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusSupplierIndex", "offset": 0, @@ -1914,7 +1931,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1814, + "astId": 9917, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -1922,7 +1939,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1819, + "astId": 9922, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusAccrued", "offset": 0, @@ -1930,15 +1947,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1823, + "astId": 9926, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)25733" + "type": "t_contract(VAIControllerInterface)51683" }, { - "astId": 1828, + "astId": 9931, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "mintedVAIs", "offset": 0, @@ -1946,7 +1963,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1831, + "astId": 9934, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "vaiMintRate", "offset": 0, @@ -1954,7 +1971,7 @@ "type": "t_uint256" }, { - "astId": 1834, + "astId": 9937, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -1962,7 +1979,7 @@ "type": "t_bool" }, { - "astId": 1836, + "astId": 9939, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -1970,7 +1987,7 @@ "type": "t_bool" }, { - "astId": 1839, + "astId": 9942, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "protocolPaused", "offset": 2, @@ -1978,7 +1995,7 @@ "type": "t_bool" }, { - "astId": 1842, + "astId": 9945, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusVAIRate", "offset": 0, @@ -1986,7 +2003,7 @@ "type": "t_uint256" }, { - "astId": 1848, + "astId": 9951, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -1994,7 +2011,7 @@ "type": "t_uint256" }, { - "astId": 1850, + "astId": 9953, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "vaiVaultAddress", "offset": 0, @@ -2002,7 +2019,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9955, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "releaseStartBlock", "offset": 0, @@ -2010,7 +2027,7 @@ "type": "t_uint256" }, { - "astId": 1854, + "astId": 9957, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "minReleaseAmount", "offset": 0, @@ -2018,7 +2035,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9963, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "borrowCapGuardian", "offset": 0, @@ -2026,7 +2043,7 @@ "type": "t_address" }, { - "astId": 1865, + "astId": 9968, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "borrowCaps", "offset": 0, @@ -2034,7 +2051,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1871, + "astId": 9974, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "treasuryGuardian", "offset": 0, @@ -2042,7 +2059,7 @@ "type": "t_address" }, { - "astId": 1874, + "astId": 9977, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "treasuryAddress", "offset": 0, @@ -2050,7 +2067,7 @@ "type": "t_address" }, { - "astId": 1877, + "astId": 9980, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "treasuryPercent", "offset": 0, @@ -2058,7 +2075,7 @@ "type": "t_uint256" }, { - "astId": 1885, + "astId": 9988, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -2066,7 +2083,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9993, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "lastContributorBlock", "offset": 0, @@ -2074,7 +2091,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1895, + "astId": 9998, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "liquidatorContract", "offset": 0, @@ -2082,15 +2099,15 @@ "type": "t_address" }, { - "astId": 1901, + "astId": 10004, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1660" + "type": "t_contract(ComptrollerLensInterface)9761" }, { - "astId": 1909, + "astId": 10012, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "supplyCaps", "offset": 0, @@ -2098,7 +2115,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1915, + "astId": 10018, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "accessControl", "offset": 0, @@ -2106,7 +2123,7 @@ "type": "t_address" }, { - "astId": 1922, + "astId": 10025, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_actionPaused", "offset": 0, @@ -2114,7 +2131,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1930, + "astId": 10033, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -2122,7 +2139,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1935, + "astId": 10038, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -2130,7 +2147,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1945, + "astId": 10048, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "approvedDelegates", "offset": 0, @@ -2138,7 +2155,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1953, + "astId": 10056, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -2146,23 +2163,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1972, + "astId": 10075, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)" }, { - "astId": 1977, + "astId": 10080, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)" }, { - "astId": 1980, + "astId": 10083, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "_facetAddresses", "offset": 0, @@ -2170,15 +2187,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1987, + "astId": 10090, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)22911" + "type": "t_contract(IPrime)42902" }, { - "astId": 1997, + "astId": 10100, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -2186,7 +2203,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 2003, + "astId": 10106, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "xvs", "offset": 0, @@ -2194,7 +2211,7 @@ "type": "t_address" }, { - "astId": 2006, + "astId": 10109, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "xvsVToken", "offset": 0, @@ -2202,7 +2219,7 @@ "type": "t_address" }, { - "astId": 2028, + "astId": 10131, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "userPoolId", "offset": 0, @@ -2210,15 +2227,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2034, + "astId": 10137, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)2023_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)10126_storage)" }, { - "astId": 2037, + "astId": 10140, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "lastPoolId", "offset": 0, @@ -2226,7 +2243,7 @@ "type": "t_uint96" }, { - "astId": 2045, + "astId": 10148, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -2234,12 +2251,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2048, + "astId": 10151, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 10158, + "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)8437" } ], "types": { @@ -2260,8 +2285,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)32634)dyn_storage": { - "base": "t_contract(VToken)32634", + "t_array(t_contract(VToken)58633)dyn_storage": { + "base": "t_contract(VToken)58633", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -2276,37 +2301,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1660": { + "t_contract(ComptrollerLensInterface)9761": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)22911": { + "t_contract(IDeviationBoundedOracle)8437": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)42902": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)992": { + "t_contract(ResilientOracleInterface)8467": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)25733": { + "t_contract(VAIControllerInterface)51683": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)32634": { + "t_contract(VToken)58633": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)32634)dyn_storage" + "value": "t_array(t_contract(VToken)58633)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -2336,19 +2366,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1967_storage" + "value": "t_struct(FacetFunctionSelectors)10070_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1775_storage" + "value": "t_struct(VenusMarketState)9878_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -2364,12 +2394,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1961_storage" + "value": "t_struct(FacetAddressAndPosition)10064_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -2378,31 +2408,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)2023_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)10126_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)2023_storage" + "value": "t_struct(PoolData)10126_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11427", + "key": "t_userDefinedValueType(PoolMarketId)19777", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1736_storage" + "value": "t_struct(Market)9839_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1961_storage": { + "t_struct(FacetAddressAndPosition)10064_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1958, + "astId": 10061, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "facetAddress", "offset": 0, @@ -2410,7 +2440,7 @@ "type": "t_address" }, { - "astId": 1960, + "astId": 10063, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "functionSelectorPosition", "offset": 20, @@ -2420,12 +2450,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1967_storage": { + "t_struct(FacetFunctionSelectors)10070_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1964, + "astId": 10067, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "functionSelectors", "offset": 0, @@ -2433,7 +2463,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1966, + "astId": 10069, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "facetAddressPosition", "offset": 0, @@ -2443,12 +2473,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1736_storage": { + "t_struct(Market)9839_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1712, + "astId": 9815, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isListed", "offset": 0, @@ -2456,7 +2486,7 @@ "type": "t_bool" }, { - "astId": 1715, + "astId": 9818, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -2464,7 +2494,7 @@ "type": "t_uint256" }, { - "astId": 1720, + "astId": 9823, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "accountMembership", "offset": 0, @@ -2472,7 +2502,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1723, + "astId": 9826, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isVenus", "offset": 0, @@ -2480,7 +2510,7 @@ "type": "t_bool" }, { - "astId": 1726, + "astId": 9829, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -2488,7 +2518,7 @@ "type": "t_uint256" }, { - "astId": 1729, + "astId": 9832, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -2496,7 +2526,7 @@ "type": "t_uint256" }, { - "astId": 1732, + "astId": 9835, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "poolId", "offset": 0, @@ -2504,7 +2534,7 @@ "type": "t_uint96" }, { - "astId": 1735, + "astId": 9838, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isBorrowAllowed", "offset": 12, @@ -2514,12 +2544,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)2023_storage": { + "t_struct(PoolData)10126_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 2012, + "astId": 10115, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "label", "offset": 0, @@ -2527,7 +2557,7 @@ "type": "t_string_storage" }, { - "astId": 2016, + "astId": 10119, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "vTokens", "offset": 0, @@ -2535,7 +2565,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 2019, + "astId": 10122, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "isActive", "offset": 0, @@ -2543,7 +2573,7 @@ "type": "t_bool" }, { - "astId": 2022, + "astId": 10125, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -2553,12 +2583,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1775_storage": { + "t_struct(VenusMarketState)9878_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1771, + "astId": 9874, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "index", "offset": 0, @@ -2566,7 +2596,7 @@ "type": "t_uint224" }, { - "astId": 1774, + "astId": 9877, "contract": "contracts/Comptroller/Diamond/facets/RewardFacet.sol:RewardFacet", "label": "block", "offset": 28, @@ -2596,7 +2626,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11427": { + "t_userDefinedValueType(PoolMarketId)19777": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bsctestnet/SetterFacet.json b/deployments/bsctestnet/SetterFacet.json index 4ceaba08f..e837adcdb 100644 --- a/deployments/bsctestnet/SetterFacet.json +++ b/deployments/bsctestnet/SetterFacet.json @@ -1,5 +1,5 @@ { - "address": "0x4fc4C41388237D13A430879417f143EF54e5BB05", + "address": "0x38DC0fcEC79675c41f3e461797A7dd99EF3baC6E", "abi": [ { "inputs": [], @@ -531,6 +531,25 @@ "name": "NewComptrollerLens", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "oldDeviationBoundedOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "NewDeviationBoundedOracle", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -1522,6 +1541,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "flashLoanPaused", @@ -1955,6 +1987,25 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "setDeviationBoundedOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2510,28 +2561,28 @@ "type": "function" } ], - "transactionHash": "0xa0ddb5e7a6590e5d6ec2fe076690ff7313521498de905635c12f78de3c02bbaf", + "transactionHash": "0x67c0e61d4e49e468458710f011c9db3abc7f8b23ad4115bff76ce5d8a1704e76", "receipt": { "to": null, - "from": "0x33C6476F88eeA28D7E7900F759B4597704Ef95B7", - "contractAddress": "0x4fc4C41388237D13A430879417f143EF54e5BB05", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0x38DC0fcEC79675c41f3e461797A7dd99EF3baC6E", "transactionIndex": 0, - "gasUsed": "3396204", + "gasUsed": "3458885", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xb9e925b1c9a083f56f4900f4220d3d40370c342622d9d0e7d92143cd3c1f11b9", - "transactionHash": "0xa0ddb5e7a6590e5d6ec2fe076690ff7313521498de905635c12f78de3c02bbaf", + "blockHash": "0xf924f664e9b858a2dd9f7ad97d0e8f863ffd752623d033f12d987f90e8c19034", + "transactionHash": "0x67c0e61d4e49e468458710f011c9db3abc7f8b23ad4115bff76ce5d8a1704e76", "logs": [], - "blockNumber": 70273629, - "cumulativeGasUsed": "3396204", + "blockNumber": 102774068, + "cumulativeGasUsed": "3458885", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 10, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPausedMarket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"ActionProtocolPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"BorrowAllowedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldPaused\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newPaused\",\"type\":\"bool\"}],\"name\":\"FlashLoanPauseChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"isWhitelisted\",\"type\":\"bool\"}],\"name\":\"IsAccountFlashLoanWhitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledForUserUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"NewAccessControl\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldComptrollerLens\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newComptrollerLens\",\"type\":\"address\"}],\"name\":\"NewComptrollerLens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationThresholdMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationThreshold\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldLiquidatorContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newLiquidatorContract\",\"type\":\"address\"}],\"name\":\"NewLiquidatorContract\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IPrime\",\"name\":\"oldPrimeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IPrime\",\"name\":\"newPrimeToken\",\"type\":\"address\"}],\"name\":\"NewPrimeToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSupplyCap\",\"type\":\"uint256\"}],\"name\":\"NewSupplyCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"}],\"name\":\"NewTreasuryAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"}],\"name\":\"NewTreasuryGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldTreasuryPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"NewTreasuryPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract VAIControllerInterface\",\"name\":\"oldVAIController\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract VAIControllerInterface\",\"name\":\"newVAIController\",\"type\":\"address\"}],\"name\":\"NewVAIController\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldVAIMintRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVAIMintRate\",\"type\":\"uint256\"}],\"name\":\"NewVAIMintRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vault_\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartBlock_\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseInterval_\",\"type\":\"uint256\"}],\"name\":\"NewVAIVaultInfo\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldVenusVAIVaultRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVenusVAIVaultRate\",\"type\":\"uint256\"}],\"name\":\"NewVenusVAIVaultRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldXVS\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newXVS\",\"type\":\"address\"}],\"name\":\"NewXVSToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldXVSVToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newXVSVToken\",\"type\":\"address\"}],\"name\":\"NewXVSVToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"PoolActiveStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"PoolFallbackStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"oldLabel\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newLabel\",\"type\":\"string\"}],\"name\":\"PoolLabelUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"_setAccessControl\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets_\",\"type\":\"address[]\"},{\"internalType\":\"enum Action[]\",\"name\":\"actions_\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}],\"name\":\"_setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"comptrollerLens_\",\"type\":\"address\"}],\"name\":\"_setComptrollerLens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"_setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"_setForcedLiquidationForUser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newLiquidatorContract_\",\"type\":\"address\"}],\"name\":\"_setLiquidatorContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_prime\",\"type\":\"address\"}],\"name\":\"_setPrimeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setProtocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"_setTreasuryData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"vaiController_\",\"type\":\"address\"}],\"name\":\"_setVAIController\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newVAIMintRate\",\"type\":\"uint256\"}],\"name\":\"_setVAIMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vault_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"releaseStartBlock_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minReleaseAmount_\",\"type\":\"uint256\"}],\"name\":\"_setVAIVaultInfo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"venusVAIVaultRate_\",\"type\":\"uint256\"}],\"name\":\"_setVenusVAIVaultRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"xvs_\",\"type\":\"address\"}],\"name\":\"_setXVSToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"xvsVToken_\",\"type\":\"address\"}],\"name\":\"_setXVSVToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets_\",\"type\":\"address[]\"},{\"internalType\":\"enum Action[]\",\"name\":\"actions_\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}],\"name\":\"setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"allowFallback\",\"type\":\"bool\"}],\"name\":\"setAllowCorePoolFallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"setFlashLoanPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"borrowAllowed\",\"type\":\"bool\"}],\"name\":\"setIsBorrowAllowed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setMintedVAIOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"}],\"name\":\"setPoolActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"string\",\"name\":\"newLabel\",\"type\":\"string\"}],\"name\":\"setPoolLabel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_prime\",\"type\":\"address\"}],\"name\":\"setPrimeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isWhiteListed\",\"type\":\"bool\"}],\"name\":\"setWhiteListFlashLoanAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the setters for the states\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setAccessControl(address)\":{\"details\":\"Allows the contract admin to set the address of access control of this contract\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"_setActionsPaused(address[],uint8[],bool)\":{\"details\":\"Allows a privileged role to pause/unpause the protocol action state\",\"params\":{\"actions_\":\"List of action ids to pause/unpause\",\"markets_\":\"Markets to pause/unpause the actions on\",\"paused_\":\"The new paused state (true=paused, false=unpaused)\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Allows the contract admin to set the closeFactor used to liquidate borrows\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"_setComptrollerLens(address)\":{\"details\":\"Set ComptrollerLens contract address\",\"params\":{\"comptrollerLens_\":\"The new ComptrollerLens contract address to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setForcedLiquidation(address,bool)\":{\"details\":\"Allows a privileged role to set enable/disable forced liquidations\",\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"_setForcedLiquidationForUser(address,address,bool)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"_setLiquidatorContract(address)\":{\"details\":\"Allows the contract admin to update the address of liquidator contract\",\"params\":{\"newLiquidatorContract_\":\"The new address of the liquidator contract\"}},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\",\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"_setMarketSupplyCaps(address[],uint256[])\":{\"details\":\"Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\",\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"_setPauseGuardian(address)\":{\"details\":\"Allows the contract admin to change the Pause Guardian\",\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"_setPriceOracle(address)\":{\"details\":\"Allows the contract admin to set a new price oracle used by the Comptroller\",\"params\":{\"newOracle\":\"The new price oracle to set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setPrimeToken(address)\":{\"params\":{\"_prime\":\"The new prime token contract to be set\"},\"returns\":{\"_0\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setProtocolPaused(bool)\":{\"details\":\"Allows a privileged role to pause/unpause protocol\",\"params\":{\"state\":\"The new state (true=paused, false=unpaused)\"},\"returns\":{\"_0\":\"bool The updated state of the protocol\"}},\"_setTreasuryData(address,address,uint256)\":{\"params\":{\"newTreasuryAddress\":\"The new address of the treasury to be set\",\"newTreasuryGuardian\":\"The new address of the treasury guardian to be set\",\"newTreasuryPercent\":\"The new treasury percent to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIController(address)\":{\"details\":\"Admin function to set a new VAI controller\",\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIMintRate(uint256)\":{\"params\":{\"newVAIMintRate\":\"The new VAI mint rate to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIVaultInfo(address,uint256,uint256)\":{\"params\":{\"minReleaseAmount_\":\"The minimum release amount to VAI Vault\",\"releaseStartBlock_\":\"The start block of release to VAI Vault\",\"vault_\":\"The address of the VAI Vault\"}},\"_setVenusVAIVaultRate(uint256)\":{\"params\":{\"venusVAIVaultRate_\":\"The amount of XVS wei per block to distribute to VAI Vault\"}},\"_setXVSToken(address)\":{\"params\":{\"xvs_\":\"The address of the XVS token\"}},\"_setXVSVToken(address)\":{\"params\":{\"xvsVToken_\":\"The address of the XVS vToken\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"setActionsPaused(address[],uint8[],bool)\":{\"params\":{\"actions_\":\"List of action ids to pause/unpause\",\"markets_\":\"Markets to pause/unpause the actions on\",\"paused_\":\"The new paused state (true=paused, false=unpaused)\"}},\"setAllowCorePoolFallback(uint96,bool)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.\",\"custom:event\":\"PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\",\"params\":{\"allowFallback\":\"True to allow fallback to Core Pool, false to disable.\",\"poolId\":\"ID of the pool to update.\"}},\"setCloseFactor(uint256)\":{\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"setCollateralFactor(address,uint256,uint256)\":{\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"vToken\":\"The market to set the factor on\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setCollateralFactor(uint96,address,uint256,uint256)\":{\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The market to set the factor on\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setFlashLoanPaused(bool)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits FlashLoanPauseChanged event\",\"params\":{\"paused\":\"True to pause flash loans, false to unpause\"}},\"setForcedLiquidation(address,bool)\":{\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"setIsBorrowAllowed(uint96,address,bool)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the pool ID is invalid.MarketConfigNotFound Reverts if the market is not listed in the pool.\",\"custom:event\":\"BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\",\"params\":{\"borrowAllowed\":\"The new borrow allowed status.\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The address of the market (vToken).\"}},\"setLiquidationIncentive(address,uint256)\":{\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\",\"vToken\":\"The market to set the liquidationIncentive for\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setLiquidationIncentive(uint96,address,uint256)\":{\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The market to set the liquidationIncentive for\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setMarketBorrowCaps(address[],uint256[])\":{\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"setMarketSupplyCaps(address[],uint256[])\":{\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"setMintedVAIOf(address,uint256)\":{\"params\":{\"amount\":\"The amount of VAI to set to the account\",\"owner\":\"The address of the account to set\"},\"returns\":{\"_0\":\"The number of minted VAI by `owner`\"}},\"setPoolActive(uint96,bool)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.\",\"custom:event\":\"PoolActiveStatusUpdated Emitted after the pool active status is updated.\",\"params\":{\"active\":\"true to enable, false to disable\",\"poolId\":\"id of the pool to update\"}},\"setPoolLabel(uint96,string)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core PoolPoolDoesNotExist Reverts if the target pool ID does not existEmptyPoolLabel Reverts if the provided label is an empty string\",\"custom:event\":\"PoolLabelUpdated Emitted after the pool label is updated\",\"params\":{\"newLabel\":\"The new label for the pool\",\"poolId\":\"ID of the pool to update\"}},\"setPriceOracle(address)\":{\"params\":{\"newOracle\":\"The new price oracle to set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"setPrimeToken(address)\":{\"params\":{\"_prime\":\"The new prime token contract to be set\"},\"returns\":{\"_0\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"setWhiteListFlashLoanAccount(address,bool)\":{\"custom:event\":\"Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\",\"params\":{\"account\":\"The account to authorize for flash loans\",\"isWhiteListed\":\"True to whitelist the account for flash loans, false to remove from whitelist\"}}},\"title\":\"SetterFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"ActionPausedMarket(address,uint8,bool)\":{\"notice\":\"Emitted when an action is paused on a market\"},\"ActionProtocolPaused(bool)\":{\"notice\":\"Emitted when protocol state is changed by admin\"},\"BorrowAllowedUpdated(uint96,address,bool,bool)\":{\"notice\":\"Emitted when the borrowAllowed flag is updated for a market\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"FlashLoanPauseChanged(bool,bool)\":{\"notice\":\"Emitted when flash loan pause status changes\"},\"IsAccountFlashLoanWhitelisted(address,bool)\":{\"notice\":\"Emitted when an account's flash loan whitelist status is updated\"},\"IsForcedLiquidationEnabledForUserUpdated(address,address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\"},\"IsForcedLiquidationEnabledUpdated(address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for all users in a market\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"NewAccessControl(address,address)\":{\"notice\":\"Emitted when access control address is changed by admin\"},\"NewBorrowCap(address,uint256)\":{\"notice\":\"Emitted when borrow cap for a vToken is changed\"},\"NewCloseFactor(uint256,uint256)\":{\"notice\":\"Emitted when close factor is changed by admin\"},\"NewCollateralFactor(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when a collateral factor for a market in a pool is changed by admin\"},\"NewComptrollerLens(address,address)\":{\"notice\":\"Emitted when ComptrollerLens address is changed\"},\"NewLiquidationIncentive(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation incentive for a market in a pool is changed by admin\"},\"NewLiquidationThreshold(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation threshold for a market in a pool is changed by admin\"},\"NewLiquidatorContract(address,address)\":{\"notice\":\"Emitted when liquidator adress is changed\"},\"NewPauseGuardian(address,address)\":{\"notice\":\"Emitted when pause guardian is changed\"},\"NewPriceOracle(address,address)\":{\"notice\":\"Emitted when price oracle is changed\"},\"NewPrimeToken(address,address)\":{\"notice\":\"Emitted when prime token contract address is changed\"},\"NewSupplyCap(address,uint256)\":{\"notice\":\"Emitted when supply cap for a vToken is changed\"},\"NewTreasuryAddress(address,address)\":{\"notice\":\"Emitted when treasury address is changed\"},\"NewTreasuryGuardian(address,address)\":{\"notice\":\"Emitted when treasury guardian is changed\"},\"NewTreasuryPercent(uint256,uint256)\":{\"notice\":\"Emitted when treasury percent is changed\"},\"NewVAIController(address,address)\":{\"notice\":\"Emitted when VAIController is changed\"},\"NewVAIMintRate(uint256,uint256)\":{\"notice\":\"Emitted when VAI mint rate is changed by admin\"},\"NewVAIVaultInfo(address,uint256,uint256)\":{\"notice\":\"Emitted when VAI Vault info is changed\"},\"NewVenusVAIVaultRate(uint256,uint256)\":{\"notice\":\"Emitted when Venus VAI Vault rate is changed\"},\"NewXVSToken(address,address)\":{\"notice\":\"Emitted when XVS token address is changed\"},\"NewXVSVToken(address,address)\":{\"notice\":\"Emitted when XVS vToken address is changed\"},\"PoolActiveStatusUpdated(uint96,bool,bool)\":{\"notice\":\"Emitted when pool active status updated\"},\"PoolFallbackStatusUpdated(uint96,bool,bool)\":{\"notice\":\"Emitted when pool Fallback status is updated\"},\"PoolLabelUpdated(uint96,string,string)\":{\"notice\":\"Emitted when pool label is updated\"}},\"kind\":\"user\",\"methods\":{\"_setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"_setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Pause/unpause certain actions\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setForcedLiquidation(address,bool)\":{\"notice\":\"Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity\"},\"_setForcedLiquidationForUser(address,address,bool)\":{\"notice\":\"Enables forced liquidations for user's borrows in a certain market. If forced liquidation is enabled, user's borrows in the market may be liquidated regardless of the account liquidity. Forced liquidation may be enabled for a user even if it is not enabled for the entire market.\"},\"_setLiquidatorContract(address)\":{\"notice\":\"Update the address of the liquidator contract\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\"},\"_setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_setPrimeToken(address)\":{\"notice\":\"Sets the prime token contract for the comptroller\"},\"_setProtocolPaused(bool)\":{\"notice\":\"Set whole protocol pause/unpause state\"},\"_setTreasuryData(address,address,uint256)\":{\"notice\":\"Set the treasury data.\"},\"_setVAIController(address)\":{\"notice\":\"Sets a new VAI controller\"},\"_setVAIMintRate(uint256)\":{\"notice\":\"Set the VAI mint rate\"},\"_setVAIVaultInfo(address,uint256,uint256)\":{\"notice\":\"Set the VAI Vault infos\"},\"_setVenusVAIVaultRate(uint256)\":{\"notice\":\"Set the amount of XVS distributed per block to VAI Vault\"},\"_setXVSToken(address)\":{\"notice\":\"Set the address of the XVS token\"},\"_setXVSVToken(address)\":{\"notice\":\"Set the address of the XVS vToken\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\"},\"setAllowCorePoolFallback(uint96,bool)\":{\"notice\":\"Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\"},\"setCloseFactor(uint256)\":{\"notice\":\"Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\"},\"setCollateralFactor(address,uint256,uint256)\":{\"notice\":\"Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\"},\"setCollateralFactor(uint96,address,uint256,uint256)\":{\"notice\":\"Sets the collateral factor and liquidation threshold for a market in the specified pool.\"},\"setFlashLoanPaused(bool)\":{\"notice\":\"Pause or unpause flash loans system-wide\"},\"setForcedLiquidation(address,bool)\":{\"notice\":\"Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\"},\"setIsBorrowAllowed(uint96,address,bool)\":{\"notice\":\"Updates the `isBorrowAllowed` flag for a market in a pool.\"},\"setLiquidationIncentive(address,uint256)\":{\"notice\":\"Sets the liquidation incentive for a market in the Core Pool only.\"},\"setLiquidationIncentive(uint96,address,uint256)\":{\"notice\":\"Sets the liquidation incentive for a market in the specified pool.\"},\"setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\"},\"setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\"},\"setMintedVAIOf(address,uint256)\":{\"notice\":\"Set the minted VAI amount of the `owner`\"},\"setPoolActive(uint96,bool)\":{\"notice\":\"updates active status for a specific pool (excluding the Core Pool)\"},\"setPoolLabel(uint96,string)\":{\"notice\":\"Updates the label for a specific pool (excluding the Core Pool)\"},\"setPriceOracle(address)\":{\"notice\":\"Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\"},\"setPrimeToken(address)\":{\"notice\":\"Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\"},\"setWhiteListFlashLoanAccount(address,bool)\":{\"notice\":\"Adds/Removes an account to the flash loan whitelist\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains all the configurational setter functions\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/SetterFacet.sol\":\"SetterFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV18Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param account The account to determine liquidity for\\n * @param redeemTokens The number of tokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\\n * without calculating accumulated interest.\\n * @return (possible error code,\\n hypothetical account liquidity in excess of collateral requirements,\\n * hypothetical account shortfall below collateral requirements)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(\\n address vToken,\\n address redeemer,\\n uint256 redeemTokens\\n ) internal view returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Determine the current account liquidity wrt collateral requirements\\n * @param account The account to get liquidity for\\n * @param weightingStrategy The weighting strategy to use:\\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\\n * @return (possible error code (semi-opaque),\\n * account liquidity in excess of collateral requirements,\\n * account shortfall below collateral requirements)\\n */\\n function _getAccountLiquidity(\\n address account,\\n WeightFunction weightingStrategy\\n ) internal view returns (uint256, uint256, uint256) {\\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n account,\\n VToken(address(0)),\\n 0,\\n 0,\\n weightingStrategy\\n );\\n\\n return (uint256(err), liquidity, shortfall);\\n }\\n}\\n\",\"keccak256\":\"0x8debfe2e7a5c6cea3cd0330963e6a28caf4e5ec30a207edce00d72499652ec88\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/SetterFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../../ComptrollerLensInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../../../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { IPrime } from \\\"../../../Tokens/Prime/IPrime.sol\\\";\\nimport { ISetterFacet } from \\\"../interfaces/ISetterFacet.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\n/**\\n * @title SetterFacet\\n * @author Venus\\n * @dev This facet contains all the setters for the states\\n * @notice This facet contract contains all the configurational setter functions\\n */\\ncontract SetterFacet is ISetterFacet, FacetBase {\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor for a market in a pool is changed by admin\\n event NewCollateralFactor(\\n uint96 indexed poolId,\\n VToken indexed vToken,\\n uint256 oldCollateralFactorMantissa,\\n uint256 newCollateralFactorMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive for a market in a pool is changed by admin\\n event NewLiquidationIncentive(\\n uint96 indexed poolId,\\n address indexed vToken,\\n uint256 oldLiquidationIncentiveMantissa,\\n uint256 newLiquidationIncentiveMantissa\\n );\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when VAIController is changed\\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\\n\\n /// @notice Emitted when VAI mint rate is changed by admin\\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\\n\\n /// @notice Emitted when protocol state is changed by admin\\n event ActionProtocolPaused(bool state);\\n\\n /// @notice Emitted when treasury guardian is changed\\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\\n\\n /// @notice Emitted when treasury address is changed\\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\\n\\n /// @notice Emitted when treasury percent is changed\\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\\n\\n /// @notice Emitted when liquidator adress is changed\\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\\n\\n /// @notice Emitted when ComptrollerLens address is changed\\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\\n\\n /// @notice Emitted when VAI Vault info is changed\\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\\n\\n /// @notice Emitted when Venus VAI Vault rate is changed\\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\\n\\n /// @notice Emitted when prime token contract address is changed\\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for all users in a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\\n event IsForcedLiquidationEnabledForUserUpdated(address indexed borrower, address indexed vToken, bool enable);\\n\\n /// @notice Emitted when XVS token address is changed\\n event NewXVSToken(address indexed oldXVS, address indexed newXVS);\\n\\n /// @notice Emitted when XVS vToken address is changed\\n event NewXVSVToken(address indexed oldXVSVToken, address indexed newXVSVToken);\\n\\n /// @notice Emitted when an account's flash loan whitelist status is updated\\n event IsAccountFlashLoanWhitelisted(address indexed account, bool indexed isWhitelisted);\\n\\n /// @notice Emitted when liquidation threshold for a market in a pool is changed by admin\\n event NewLiquidationThreshold(\\n uint96 indexed poolId,\\n VToken indexed vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when the borrowAllowed flag is updated for a market\\n event BorrowAllowedUpdated(uint96 indexed poolId, address indexed market, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when pool active status updated\\n event PoolActiveStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when pool label is updated\\n event PoolLabelUpdated(uint96 indexed poolId, string oldLabel, string newLabel);\\n\\n /// @notice Emitted when pool Fallback status is updated\\n event PoolFallbackStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when flash loan pause status changes\\n event FlashLoanPauseChanged(bool oldPaused, bool newPaused);\\n\\n /**\\n * @notice Compare two addresses to ensure they are different\\n * @param oldAddress The original address to compare\\n * @param newAddress The new address to compare\\n */\\n modifier compareAddress(address oldAddress, address newAddress) {\\n require(oldAddress != newAddress, \\\"old address is same as new address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Compare two values to ensure they are different\\n * @param oldValue The original value to compare\\n * @param newValue The new value to compare\\n */\\n modifier compareValue(uint256 oldValue, uint256 newValue) {\\n require(oldValue != newValue, \\\"old value is same as new value\\\");\\n _;\\n }\\n\\n /**\\n * @notice Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\\n * @param newOracle The new price oracle to set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\\n return __setPriceOracle(newOracle);\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\\n * @param newOracle The new price oracle to set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\\n return __setPriceOracle(newOracle);\\n }\\n\\n /**\\n * @notice Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint256 0=success, otherwise will revert\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\\n return __setCloseFactor(newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint256 0=success, otherwise will revert\\n */\\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\\n return __setCloseFactor(newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Allows the contract admin to set the address of access control of this contract\\n * @param newAccessControlAddress New address for the access control\\n * @return uint256 0=success, otherwise will revert\\n */\\n function _setAccessControl(\\n address newAccessControlAddress\\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(newAccessControlAddress);\\n\\n address oldAccessControlAddress = accessControl;\\n\\n accessControl = newAccessControlAddress;\\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n return __setCollateralFactor(corePoolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\\n }\\n\\n /**\\n * @notice Sets the liquidation incentive for a market in the Core Pool only.\\n * @param vToken The market to set the liquidationIncentive for\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setLiquidationIncentive(\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setLiquidationIncentive(address,uint256)\\\");\\n return __setLiquidationIncentive(corePoolId, vToken, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateral factor and liquidation threshold for a market in the specified pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setCollateralFactor(uint96,address,uint256,uint256)\\\");\\n return __setCollateralFactor(poolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\\n }\\n\\n /**\\n * @notice Sets the liquidation incentive for a market in the specified pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the liquidationIncentive for\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setLiquidationIncentive(uint96,address,uint256)\\\");\\n return __setLiquidationIncentive(poolId, vToken, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Update the address of the liquidator contract\\n * @dev Allows the contract admin to update the address of liquidator contract\\n * @param newLiquidatorContract_ The new address of the liquidator contract\\n */\\n function _setLiquidatorContract(\\n address newLiquidatorContract_\\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(newLiquidatorContract_);\\n address oldLiquidatorContract = liquidatorContract;\\n liquidatorContract = newLiquidatorContract_;\\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @dev Allows the contract admin to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(\\n address newPauseGuardian\\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\\n ensureAdmin();\\n ensureNonzeroAddress(newPauseGuardian);\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\\n */\\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\\n }\\n\\n /**\\n * @notice Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\\n */\\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\\n }\\n\\n /**\\n * @notice Set whole protocol pause/unpause state\\n * @dev Allows a privileged role to pause/unpause protocol\\n * @param state The new state (true=paused, false=unpaused)\\n * @return bool The updated state of the protocol\\n */\\n function _setProtocolPaused(bool state) external returns (bool) {\\n ensureAllowed(\\\"_setProtocolPaused(bool)\\\");\\n\\n protocolPaused = state;\\n emit ActionProtocolPaused(state);\\n return state;\\n }\\n\\n /**\\n * @notice Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\\n * @param markets_ Markets to pause/unpause the actions on\\n * @param actions_ List of action ids to pause/unpause\\n * @param paused_ The new paused state (true=paused, false=unpaused)\\n */\\n function setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\\n __setActionsPaused(markets_, actions_, paused_);\\n }\\n\\n /**\\n * @notice Pause/unpause certain actions\\n * @dev Allows a privileged role to pause/unpause the protocol action state\\n * @param markets_ Markets to pause/unpause the actions on\\n * @param actions_ List of action ids to pause/unpause\\n * @param paused_ The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\\n __setActionsPaused(markets_, actions_, paused_);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function setActionPausedInternal(address market, Action action, bool paused) internal {\\n ensureListed(getCorePoolMarket(market));\\n _actionPaused[market][uint256(action)] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @notice Sets a new VAI controller\\n * @dev Admin function to set a new VAI controller\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setVAIController(\\n VAIControllerInterface vaiController_\\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(address(vaiController_));\\n\\n VAIControllerInterface oldVaiController = vaiController;\\n vaiController = vaiController_;\\n emit NewVAIController(oldVaiController, vaiController_);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the VAI mint rate\\n * @param newVAIMintRate The new VAI mint rate to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setVAIMintRate(\\n uint256 newVAIMintRate\\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n uint256 oldVAIMintRate = vaiMintRate;\\n vaiMintRate = newVAIMintRate;\\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the minted VAI amount of the `owner`\\n * @param owner The address of the account to set\\n * @param amount The amount of VAI to set to the account\\n * @return The number of minted VAI by `owner`\\n */\\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\\n checkProtocolPauseState();\\n\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \\\"VAI is paused\\\");\\n // Check caller is vaiController\\n if (msg.sender != address(vaiController)) {\\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\\n }\\n mintedVAIs[owner] = amount;\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the treasury data.\\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\\n * @param newTreasuryAddress The new address of the treasury to be set\\n * @param newTreasuryPercent The new treasury percent to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256) {\\n // Check caller is admin\\n ensureAdminOr(treasuryGuardian);\\n\\n require(newTreasuryPercent < 1e18, \\\"percent >= 100%\\\");\\n ensureNonzeroAddress(newTreasuryGuardian);\\n ensureNonzeroAddress(newTreasuryAddress);\\n\\n address oldTreasuryGuardian = treasuryGuardian;\\n address oldTreasuryAddress = treasuryAddress;\\n uint256 oldTreasuryPercent = treasuryPercent;\\n\\n treasuryGuardian = newTreasuryGuardian;\\n treasuryAddress = newTreasuryAddress;\\n treasuryPercent = newTreasuryPercent;\\n\\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /*** Venus Distribution ***/\\n\\n /**\\n * @dev Set ComptrollerLens contract address\\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptrollerLens(\\n ComptrollerLensInterface comptrollerLens_\\n ) external virtual compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\\n ensureAdmin();\\n ensureNonzeroAddress(address(comptrollerLens_));\\n address oldComptrollerLens = address(comptrollerLens);\\n comptrollerLens = comptrollerLens_;\\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the amount of XVS distributed per block to VAI Vault\\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\\n */\\n function _setVenusVAIVaultRate(\\n uint256 venusVAIVaultRate_\\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\\n ensureAdmin();\\n if (vaiVaultAddress != address(0)) {\\n releaseToVault();\\n }\\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\\n venusVAIVaultRate = venusVAIVaultRate_;\\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\\n }\\n\\n /**\\n * @notice Set the VAI Vault infos\\n * @param vault_ The address of the VAI Vault\\n * @param releaseStartBlock_ The start block of release to VAI Vault\\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\\n */\\n function _setVAIVaultInfo(\\n address vault_,\\n uint256 releaseStartBlock_,\\n uint256 minReleaseAmount_\\n ) external compareAddress(vaiVaultAddress, vault_) {\\n ensureAdmin();\\n ensureNonzeroAddress(vault_);\\n if (vaiVaultAddress != address(0)) {\\n releaseToVault();\\n }\\n\\n vaiVaultAddress = vault_;\\n releaseStartBlock = releaseStartBlock_;\\n minReleaseAmount = minReleaseAmount_;\\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\\n }\\n\\n /**\\n * @notice Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\\n * @param _prime The new prime token contract to be set\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function setPrimeToken(IPrime _prime) external returns (uint256) {\\n return __setPrimeToken(_prime);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime The new prime token contract to be set\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPrimeToken(IPrime _prime) external returns (uint256) {\\n return __setPrimeToken(_prime);\\n }\\n\\n /**\\n * @notice Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n __setForcedLiquidation(vTokenBorrowed, enable);\\n }\\n\\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @dev Allows a privileged role to set enable/disable forced liquidations\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n __setForcedLiquidation(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for user's borrows in a certain market. If forced\\n * liquidation is enabled, user's borrows in the market may be liquidated regardless of\\n * the account liquidity. Forced liquidation may be enabled for a user even if it is not\\n * enabled for the entire market.\\n * @param borrower The address of the borrower\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external {\\n ensureAllowed(\\\"_setForcedLiquidationForUser(address,address,bool)\\\");\\n if (vTokenBorrowed != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledForUserUpdated(borrower, vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Set the address of the XVS token\\n * @param xvs_ The address of the XVS token\\n */\\n function _setXVSToken(address xvs_) external {\\n ensureAdmin();\\n ensureNonzeroAddress(xvs_);\\n\\n emit NewXVSToken(xvs, xvs_);\\n xvs = xvs_;\\n }\\n\\n /**\\n * @notice Set the address of the XVS vToken\\n * @param xvsVToken_ The address of the XVS vToken\\n */\\n function _setXVSVToken(address xvsVToken_) external {\\n ensureAdmin();\\n ensureNonzeroAddress(xvsVToken_);\\n\\n address underlying = VToken(xvsVToken_).underlying();\\n require(underlying == xvs, \\\"invalid xvs vtoken address\\\");\\n\\n emit NewXVSVToken(xvsVToken, xvsVToken_);\\n xvsVToken = xvsVToken_;\\n }\\n\\n /**\\n * @notice Adds/Removes an account to the flash loan whitelist\\n * @param account The account to authorize for flash loans\\n * @param isWhiteListed True to whitelist the account for flash loans, false to remove from whitelist\\n * @custom:event Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\\n */\\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external {\\n ensureAllowed(\\\"setWhiteListFlashLoanAccount(address,bool)\\\");\\n ensureNonzeroAddress(account);\\n\\n // If the account's status is already the same as the desired status, do nothing\\n if (authorizedFlashLoan[account] == isWhiteListed) {\\n return;\\n }\\n\\n authorizedFlashLoan[account] = isWhiteListed;\\n emit IsAccountFlashLoanWhitelisted(account, isWhiteListed);\\n }\\n\\n /**\\n * @notice Pause or unpause flash loans system-wide\\n * @param paused True to pause flash loans, false to unpause\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanPauseChanged event\\n */\\n function setFlashLoanPaused(bool paused) external {\\n ensureAllowed(\\\"setFlashLoanPaused(bool)\\\");\\n\\n // Check if value is actually changing\\n if (flashLoanPaused == paused) {\\n return; // No change needed\\n }\\n\\n emit FlashLoanPauseChanged(flashLoanPaused, paused);\\n flashLoanPaused = paused;\\n }\\n\\n /**\\n * @notice Updates the label for a specific pool (excluding the Core Pool)\\n * @param poolId ID of the pool to update\\n * @param newLabel The new label for the pool\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist\\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string\\n * @custom:event PoolLabelUpdated Emitted after the pool label is updated\\n */\\n function setPoolLabel(uint96 poolId, string calldata newLabel) external {\\n ensureAllowed(\\\"setPoolLabel(uint96,string)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n if (bytes(newLabel).length == 0) revert EmptyPoolLabel();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (keccak256(bytes(pool.label)) == keccak256(bytes(newLabel))) {\\n return;\\n }\\n\\n emit PoolLabelUpdated(poolId, pool.label, newLabel);\\n pool.label = newLabel;\\n }\\n\\n /**\\n * @notice updates active status for a specific pool (excluding the Core Pool)\\n * @param poolId id of the pool to update\\n * @param active true to enable, false to disable\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:event PoolActiveStatusUpdated Emitted after the pool active status is updated.\\n */\\n function setPoolActive(uint96 poolId, bool active) external {\\n ensureAllowed(\\\"setPoolActive(uint96,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (pool.isActive == active) {\\n return;\\n }\\n\\n emit PoolActiveStatusUpdated(poolId, pool.isActive, active);\\n pool.isActive = active;\\n }\\n\\n /**\\n * @notice Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\\n * @param poolId ID of the pool to update.\\n * @param allowFallback True to allow fallback to Core Pool, false to disable.\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:event PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\\n */\\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external {\\n ensureAllowed(\\\"setAllowCorePoolFallback(uint96,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (pool.allowCorePoolFallback == allowFallback) {\\n return;\\n }\\n\\n emit PoolFallbackStatusUpdated(poolId, pool.allowCorePoolFallback, allowFallback);\\n pool.allowCorePoolFallback = allowFallback;\\n }\\n\\n /**\\n * @notice Updates the `isBorrowAllowed` flag for a market in a pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The address of the market (vToken).\\n * @param borrowAllowed The new borrow allowed status.\\n * @custom:error PoolDoesNotExist Reverts if the pool ID is invalid.\\n * @custom:error MarketConfigNotFound Reverts if the market is not listed in the pool.\\n * @custom:event BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\\n */\\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external {\\n ensureAllowed(\\\"setIsBorrowAllowed(uint96,address,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\\n Market storage m = _poolMarkets[index];\\n\\n if (!m.isListed) {\\n revert MarketConfigNotFound();\\n }\\n\\n if (m.isBorrowAllowed == borrowAllowed) {\\n return;\\n }\\n\\n emit BorrowAllowedUpdated(poolId, vToken, m.isBorrowAllowed, borrowAllowed);\\n m.isBorrowAllowed = borrowAllowed;\\n }\\n\\n /**\\n * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle\\n * @param newOracle The new price oracle to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setPriceOracle(\\n ResilientOracleInterface newOracle\\n ) internal compareAddress(address(oracle), address(newOracle)) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(address(newOracle));\\n\\n // Track the old oracle for the comptroller\\n ResilientOracleInterface oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the close factor. Used by _setCloseFactor and setCloseFactor\\n * @param newCloseFactorMantissa The new close factor to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setCloseFactor(\\n uint256 newCloseFactorMantissa\\n ) internal compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n\\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\\n\\n //-- Check close factor <= 0.9\\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\\n //-- Check close factor >= 0.05\\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\\n\\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the collateral factor and the liquidation threshold. Used by setCollateralFactor\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor to be set\\n * @param newLiquidationThresholdMantissa The new liquidation threshold to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) internal returns (uint256) {\\n ensureNonzeroAddress(address(vToken));\\n\\n // Check if pool exists\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n // Verify market is listed in the pool\\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, address(vToken))];\\n ensureListed(market);\\n\\n //-- Check collateral factor <= 1\\n if (newCollateralFactorMantissa > mantissaOne) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > mantissaOne) {\\n return fail(Error.INVALID_LIQUIDATION_THRESHOLD, FailureInfo.SET_LIQUIDATION_THRESHOLD_VALIDATION);\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n return\\n fail(\\n Error.INVALID_LIQUIDATION_THRESHOLD,\\n FailureInfo.COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n );\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with poolId, asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(poolId, vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n\\n emit NewLiquidationThreshold(\\n poolId,\\n vToken,\\n oldLiquidationThresholdMantissa,\\n newLiquidationThresholdMantissa\\n );\\n }\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the liquidation incentive. Used by setLiquidationIncentive\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the Incentive for\\n * @param newLiquidationIncentiveMantissa The new liquidation incentive to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n )\\n internal\\n compareValue(\\n _poolMarkets[getPoolMarketIndex(poolId, vToken)].liquidationIncentiveMantissa,\\n newLiquidationIncentiveMantissa\\n )\\n returns (uint256)\\n {\\n // Check if pool exists\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n // Verify market is listed in the pool\\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, vToken)];\\n ensureListed(market);\\n\\n require(newLiquidationIncentiveMantissa >= mantissaOne, \\\"incentive < 1e18\\\");\\n\\n emit NewLiquidationIncentive(\\n poolId,\\n vToken,\\n market.liquidationIncentiveMantissa,\\n newLiquidationIncentiveMantissa\\n );\\n\\n // Set liquidation incentive to new incentive\\n market.liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the borrow caps. Used by _setMarketBorrowCaps and setMarketBorrowCaps\\n * @param vTokens The markets to set the borrow caps on\\n * @param newBorrowCaps The new borrow caps to be set\\n */\\n function __setMarketBorrowCaps(VToken[] memory vTokens, uint256[] memory newBorrowCaps) internal {\\n ensureAllowed(\\\"_setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @dev Updates the supply caps. Used by _setMarketSupplyCaps and setMarketSupplyCaps\\n * @param vTokens The markets to set the supply caps on\\n * @param newSupplyCaps The new supply caps to be set\\n */\\n function __setMarketSupplyCaps(VToken[] memory vTokens, uint256[] memory newSupplyCaps) internal {\\n ensureAllowed(\\\"_setMarketSupplyCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numSupplyCaps = newSupplyCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @dev Updates the prime token. Used by _setPrimeToken and setPrimeToken\\n * @param _prime The new prime token to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setPrimeToken(IPrime _prime) internal returns (uint) {\\n ensureAdmin();\\n ensureNonzeroAddress(address(_prime));\\n\\n IPrime oldPrime = prime;\\n prime = _prime;\\n emit NewPrimeToken(oldPrime, _prime);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the forced liquidation. Used by _setForcedLiquidation and setForcedLiquidation\\n * @param vTokenBorrowed The market to set the forced liquidation on\\n * @param enable Whether to enable forced liquidations\\n */\\n function __setForcedLiquidation(address vTokenBorrowed, bool enable) internal {\\n ensureAllowed(\\\"_setForcedLiquidation(address,bool)\\\");\\n if (vTokenBorrowed != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @dev Updates the actions paused. Used by _setActionsPaused and setActionsPaused\\n * @param markets_ The markets to set the actions paused on\\n * @param actions_ The actions to set the paused state on\\n * @param paused_ The new paused state to be set\\n */\\n function __setActionsPaused(address[] memory markets_, Action[] memory actions_, bool paused_) internal {\\n ensureAllowed(\\\"_setActionsPaused(address[],uint8[],bool)\\\");\\n\\n uint256 numMarkets = markets_.length;\\n uint256 numActions = actions_.length;\\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe7cdb06772450e4e6512564266c5830f8a84bdfc8a705c720613b26025f75b5\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../../../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../../../Comptroller/ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../../../Tokens/Prime/IPrime.sol\\\";\\n\\ninterface ISetterFacet {\\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\\n\\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\\n\\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\\n\\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\\n\\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\\n\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256);\\n\\n function setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256);\\n\\n function setLiquidationIncentive(\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256);\\n\\n function setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256);\\n\\n function _setLiquidatorContract(address newLiquidatorContract_) external;\\n\\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\\n\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\\n\\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\\n\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\\n\\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\\n\\n function _setProtocolPaused(bool state) external returns (bool);\\n\\n function setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\\n\\n function _setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\\n\\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\\n\\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\\n\\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\\n\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256);\\n\\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external returns (uint256);\\n\\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\\n\\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\\n\\n function _setForcedLiquidation(address vToken, bool enable) external;\\n\\n function setPrimeToken(IPrime _prime) external returns (uint256);\\n\\n function _setPrimeToken(IPrime _prime) external returns (uint);\\n\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external;\\n\\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external;\\n\\n function _setXVSToken(address xvs_) external;\\n\\n function _setXVSVToken(address xvsVToken_) external;\\n\\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external;\\n\\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external;\\n\\n function setPoolActive(uint96 poolId, bool active) external;\\n\\n function setPoolLabel(uint96 poolId, string calldata newLabel) external;\\n\\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external;\\n\\n function setFlashLoanPaused(bool paused) external;\\n}\\n\",\"keccak256\":\"0xed09149ebd3ab5080875365f39e08f148ca035db8f99af908ce9021b290229c0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b50613c658061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106104bc575f3560e01c80637fb8e8cd11610279578063bec04f7211610156578063dce15449116100ca578063e87554461161008f578063e875544614610b9f578063f445d70314610ba8578063f519fc3014610bd5578063f851a44014610be8578063fa6331d814610bfa578063fd51a3ad14610c03575f80fd5b8063dce1544914610b0d578063dcfbc0c714610b20578063e0f6123d14610b33578063e37d4b7914610b55578063e85a296014610b8c575f80fd5b8063c7ee005e1161011b578063c7ee005e14610aba578063d136af441461072a578063d24febad14610acd578063d3270f9914610ae0578063d463654c14610af3578063d6ad5c3914610afa575f80fd5b8063bec04f7214610a5f578063bf32442d14610a68578063c32094c7146108e9578063c5b4db5514610a79578063c5f956af14610aa7575f80fd5b80639bd8f6e8116101ed578063b2eafc39116101b2578063b2eafc3914610999578063b8324c7c146109ac578063b88d846b14610a07578063bb82aa5e14610a1a578063bb85745014610a2d578063bbb8864a14610a40575f80fd5b80639bd8f6e81461093a5780639bf34cbb1461094d5780639cfdd9e614610960578063a657e57914610973578063a89766dd14610986575f80fd5b8063919a37361161023e578063919a3736146108c35780639254f5e5146108d65780639460c8b5146108e957806394b2294b146108fc57806396c99064146109055780639bb27d6214610927575f80fd5b80637fb8e8cd146108625780638a7dc1651461086f5780638b3113f61461073d5780638c1ac18a1461088e5780639159b177146108b0575f80fd5b806342adb211116103a75780635cc4fdeb1161031b578063719f701b116102e0578063719f701b146107ce57806373769099146107d757806376551383146108175780637938146f146108295780637d172bd51461083c5780637dc0d1d01461084f575f80fd5b80635cc4fdeb146107765780635dd3fc9d146107895780635f5af1aa146107a8578063607ef6c1146105935780636662c7c9146107bb575f80fd5b80634ef233fc1161036c5780634ef233fc1461071757806351a485e41461072a578063522c656b1461073d57806352d84d1e14610750578063530e784f1461076357806355ee1fe114610763575f80fd5b806342adb211146106ac5780634964f48c146106bf5780634a584432146106d25780634d99c776146106f15780634e0853db14610704575f80fd5b806324aaa2201161043e5780632ec04124116104035780632ec041241461063c578063317b0b771461056b578063354392401461064f5780634088c73e1461066257806341a18d2c1461066f578063425fad5814610699575f80fd5b806324aaa220146105e457806326782247146105f75780632a6a60651461060a5780632b5d790c146105e45780632bc7e29e1461061d575f80fd5b806312348e961161048457806312348e961461056b57806317db21631461057e578063186db48f1461059357806321af4569146105a657806324a3d622146105d1575f80fd5b806302c3bcbb146104c057806304ef9d58146104f257806308e0225c146104fb5780630db4b4e51461052557806310b983381461052e575b5f80fd5b6104df6104ce366004613144565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6104df60225481565b6104df61050936600461315f565b601360209081525f928352604080842090915290825290205481565b6104df601d5481565b61055b61053c36600461315f565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016104e9565b6104df610579366004613196565b610c16565b61059161058c3660046131ba565b610c26565b005b6105916105a136600461324a565b610cda565b601e546105b9906001600160a01b031681565b6040516001600160a01b0390911681526020016104e9565b600a546105b9906001600160a01b031681565b6105916105f23660046132b1565b610d4b565b6001546105b9906001600160a01b031681565b61055b61061836600461332f565b610dbf565b6104df61062b366004613144565b60166020525f908152604090205481565b6104df61064a366004613196565b610e55565b6104df61065d366004613365565b610ed8565b60185461055b9060ff1681565b6104df61067d36600461315f565b601260209081525f928352604080842090915290825290205481565b60185461055b9062010000900460ff1681565b6105916106ba3660046133a1565b610f0f565b6105916106cd3660046133cd565b610fb7565b6104df6106e0366004613144565b601f6020525f908152604090205481565b6104df6106ff3660046133e7565b6110ec565b610591610712366004613401565b611109565b610591610725366004613144565b6111cc565b61059161073836600461324a565b6112fa565b61059161074b3660046133a1565b611365565b6105b961075e366004613196565b611373565b6104df610771366004613144565b61139b565b6104df610784366004613401565b6113a5565b6104df610797366004613144565b602b6020525f908152604090205481565b6104df6107b6366004613144565b6113d3565b6105916107c9366004613196565b61146a565b6104df601c5481565b6107ff6107e5366004613144565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016104e9565b60185461055b90610100900460ff1681565b6105916108373660046133cd565b6114f6565b601b546105b9906001600160a01b031681565b6004546105b9906001600160a01b031681565b60395461055b9060ff1681565b6104df61087d366004613144565b60146020525f908152604090205481565b61055b61089c366004613144565b602d6020525f908152604090205460ff1681565b6104df6108be366004613433565b61161d565b6105916108d1366004613144565b611656565b6015546105b9906001600160a01b031681565b6104df6108f7366004613144565b6116c2565b6104df60075481565b610918610913366004613474565b6116cc565b6040516104e9939291906134bb565b6025546105b9906001600160a01b031681565b6104df6109483660046134e4565b611779565b6104df61095b366004613144565b6117a6565b6104df61096e366004613144565b61183c565b6037546107ff906001600160601b031681565b61059161099436600461350e565b6118d3565b6020546105b9906001600160a01b031681565b6109e36109ba366004613144565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104e9565b610591610a15366004613529565b611a14565b6002546105b9906001600160a01b031681565b610591610a3b366004613144565b611b78565b6104df610a4e366004613144565b602a6020525f908152604090205481565b6104df60175481565b6033546001600160a01b03166105b9565b610a8f6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b0390911681526020016104e9565b6021546105b9906001600160a01b031681565b6031546105b9906001600160a01b031681565b6104df610adb3660046135a5565b611c0d565b6026546105b9906001600160a01b031681565b6107ff5f81565b610591610b0836600461332f565b611d74565b6105b9610b1b3660046134e4565b611e1d565b6003546105b9906001600160a01b031681565b61055b610b41366004613144565b60386020525f908152604090205460ff1681565b6109e3610b63366004613144565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61055b610b9a3660046135c2565b611e51565b6104df60055481565b61055b610bb636600461315f565b603260209081525f928352604080842090915290825290205460ff1681565b6104df610be3366004613144565b611e95565b5f546105b9906001600160a01b031681565b6104df601a5481565b6104df610c113660046134e4565b611f2c565b5f610c2082611fd0565b92915050565b610c47604051806060016040528060328152602001613a34603291396120aa565b6015546001600160a01b03838116911614610c6d57610c6d610c688361215a565b61217c565b6001600160a01b038381165f81815260326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fc080966e9e93529edc1b244180c245bc60f3d86f1e690a17651a5e428746a8cd91015b60405180910390a3505050565b610d458484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f920191909152506121c192505050565b50505050565b610db88585808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284375f92019190915250869250612311915050565b5050505050565b5f610dfe6040518060400160405280601881526020017f5f73657450726f746f636f6c50617573656428626f6f6c2900000000000000008152506120aa565b60188054831515620100000262ff0000199091161790556040517fd7500633dd3ddd74daa7af62f8c8404c7fe4a81da179998db851696bed004b3890610e4990841515815260200190565b60405180910390a15090565b5f60175482808203610e825760405162461bcd60e51b8152600401610e79906135f1565b60405180910390fd5b610e8a6123a0565b601780549085905560408051828152602081018790527f73747d68b346dce1e932bcd238282e7ac84c01569e1f8d0469c222fdc6e9d5a491015b60405180910390a15f9350505b5050919050565b5f610efa6040518060600160405280602f8152602001613a8f602f91396120aa565b610f058484846123ec565b90505b9392505050565b610f306040518060600160405280602a8152602001613abe602a91396120aa565b610f398261253e565b6001600160a01b0382165f9081526038602052604090205481151560ff909116151503610f64575050565b6001600160a01b0382165f81815260386020526040808220805460ff191685151590811790915590519092917f1f4df5032f431b9890646a781be28b0d693e581666d1a80be27ae3959069172291a35050565b610ff56040518060400160405280601a81526020017f736574506f6f6c4163746976652875696e7439362c626f6f6c290000000000008152506120aa565b6037546001600160601b03908116908316111561103057604051632db8671b60e11b81526001600160601b0383166004820152602401610e79565b6001600160601b03821661105757604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151560ff90911615150361108757505050565b60028101546040805160ff9092161515825283151560208301526001600160601b038516917f75e42fceb039532886a9d75717e843bfef67fd7f6f91f0fc5b1d48e9ce8a1ba9910160405180910390a2600201805460ff191691151591909117905550565b6001600160a01b031660a09190911b6001600160a01b0319161790565b601b546001600160a01b039081169084908116820361113a5760405162461bcd60e51b8152600401610e799061363c565b6111426123a0565b61114b8561253e565b601b546001600160a01b0316156111645761116461258c565b601b80546001600160a01b0319166001600160a01b038716908117909155601c859055601d84905560408051868152602081018690527f7059037d74ee16b0fb06a4a30f3348dd2635f301f92e373c92899a25a522ef6e910160405180910390a25050505050565b6111d46123a0565b6111dd8161253e565b5f816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561121a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123e919061367e565b6033549091506001600160a01b0380831691161461129e5760405162461bcd60e51b815260206004820152601a60248201527f696e76616c6964207876732076746f6b656e20616464726573730000000000006044820152606401610e79565b6034546040516001600160a01b038085169216907f2565e1579c0926afb7113edbfd85373e85cadaa3e0346f04de19686a2bb86ed1905f90a350603480546001600160a01b0319166001600160a01b0392909216919091179055565b610d458484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f9201919091525061271b92505050565b61136f828261286b565b5050565b600d8181548110611382575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610c208261290b565b5f6113c76040518060600160405280602c8152602001613b34602c91396120aa565b610f055f8585856129a2565b600a545f906001600160a01b03908116908390811682036114065760405162461bcd60e51b8152600401610e799061363c565b61140e6123a0565b6114178461253e565b600a80546001600160a01b038681166001600160a01b03198316179092556040519116907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90610ec49083908890613699565b601a548180820361148d5760405162461bcd60e51b8152600401610e79906135f1565b6114956123a0565b601b546001600160a01b0316156114ae576114ae61258c565b601a80549084905560408051828152602081018690527fe81d4ac15e5afa1e708e66664eddc697177423d950d133bda8262d8885e6da3b91015b60405180910390a150505050565b611517604051806060016040528060258152602001613b89602591396120aa565b6037546001600160601b03908116908316111561155257604051632db8671b60e11b81526001600160601b0383166004820152602401610e79565b6001600160601b03821661157957604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151561010090910460ff161515036115ad57505050565b60028101546040805161010090920460ff161515825283151560208301526001600160601b038516917f9d2a9183b06e3492f91d3d88ae222e700c8873dd0068f9c3fc783eccb96a1ec4910160405180910390a260020180549115156101000261ff001990921691909117905550565b5f61163f604051806060016040528060338152602001613bae603391396120aa565b61164b858585856129a2565b90505b949350505050565b61165e6123a0565b6116678161253e565b6033546040516001600160a01b038084169216907ffe7fd0d872def0f65050e9f38fc6691d0c192c694a56f09b04bec5fb2ea61f2b905f90a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5f610c2082612bbf565b60366020525f90815260409020805481906116e6906136b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611712906136b3565b801561175d5780601f106117345761010080835404028352916020019161175d565b820191905f5260205f20905b81548152906001019060200180831161174057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f61179b604051806060016040528060288152602001613be1602891396120aa565b610f085f84846123ec565b6026545f906001600160a01b03908116908390811682036117d95760405162461bcd60e51b8152600401610e799061363c565b6117e16123a0565b6117ea8461253e565b602680546001600160a01b038681166001600160a01b0319831681179093556040519116917f0f7eb572d1b3053a0a3a33c04151364cf88d163182a5e4e1088cb8e52321e08a91610ec4918491613699565b6015545f906001600160a01b039081169083908116820361186f5760405162461bcd60e51b8152600401610e799061363c565b6118776123a0565b6118808461253e565b601580546001600160a01b038681166001600160a01b03198316179092556040519116907fe1ddcb2dab8e5b03cfc8c67a0d5861d91d16f7bd2612fd381faf4541d212c9b290610ec49083908890613699565b6118f4604051806060016040528060278152602001613c09602791396120aa565b6037546001600160601b03908116908416111561192f57604051632db8671b60e11b81526001600160601b0384166004820152602401610e79565b5f61193a84846110ec565b5f81815260096020526040902080549192509060ff1661196d57604051630665210960e21b815260040160405180910390fd5b82151581600601600c9054906101000a900460ff16151503611990575050505050565b600681015460408051600160601b90920460ff161515825284151560208301526001600160a01b038616916001600160601b038816917fe40f9c4af130bdb5bd1650ab4bc918dba9d900fa94685f0113e72a6cfe6c5fcc910160405180910390a36006018054921515600160601b0260ff60601b1990931692909217909155505050565b611a526040518060400160405280601b81526020017f736574506f6f6c4c6162656c2875696e7439362c737472696e672900000000008152506120aa565b6037546001600160601b039081169084161115611a8d57604051632db8671b60e11b81526001600160601b0384166004820152602401610e79565b6001600160601b038316611ab457604051630203217b60e61b815260040160405180910390fd5b5f819003611ad55760405163522e397360e11b815260040160405180910390fd5b6001600160601b0383165f90815260366020526040908190209051611afd90849084906136eb565b60405190819003812090611b129083906136fa565b604051809103902003611b255750505050565b836001600160601b03167f1ebc260ee8077871ff0b70b184ff9dac4ecee8b0f7dcc4f3a3f5068549f5078e825f018585604051611b6493929190613794565b60405180910390a280610db883858361388b565b6025546001600160a01b0390811690829081168203611ba95760405162461bcd60e51b8152600401610e799061363c565b611bb16123a0565b611bba8361253e565b602580546001600160a01b038581166001600160a01b03198316179092556040519116907fa5ea5616d5f6dbbaa62fdfcf3856723216eed485c394d9e51ec8e6d40e1d1ac1906114e89083908790613699565b6020545f90611c24906001600160a01b0316612c34565b670de0b6b3a76400008210611c6d5760405162461bcd60e51b815260206004820152600f60248201526e70657263656e74203e3d203130302560881b6044820152606401610e79565b611c768461253e565b611c7f8361253e565b6020805460218054602280546001600160a01b03198086166001600160a01b038c8116919091179097558316898716179093558690556040519284169316917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e890611ced9085908a90613699565b60405180910390a17f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac8287604051611d26929190613699565b60405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a15f5b979650505050505050565b611db26040518060400160405280601881526020017f736574466c6173684c6f616e50617573656428626f6f6c2900000000000000008152506120aa565b60395481151560ff909116151503611dc75750565b6039546040805160ff9092161515825282151560208301527f79bcfb2700d56371c7684799f99d64cbcd91f1e360f8048a42c9ba534be7c0a8910160405180910390a16039805460ff1916911515919091179055565b6008602052815f5260405f208181548110611e36575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611e7b57611e7b613628565b815260208101919091526040015f205460ff169392505050565b6028545f906001600160a01b0390811690839081168203611ec85760405162461bcd60e51b8152600401610e799061363c565b611ed06123a0565b611ed98461253e565b602880546001600160a01b038681166001600160a01b03198316179092556040519116907f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd490610ec49083908890613699565b5f611f35612c8f565b60185460ff16158015611f505750601854610100900460ff16155b611f8c5760405162461bcd60e51b815260206004820152600d60248201526c159052481a5cc81c185d5cd959609a1b6044820152606401610e79565b6015546001600160a01b03163314611fb157611faa600e6016612cdd565b9050610c20565b6001600160a01b0383165f908152601660205260408120839055610f08565b5f60055482808203611ff45760405162461bcd60e51b8152600401610e79906135f1565b611ffc6123a0565b604080516020808201835286825282518082018452670c7d713b49da00008152835191820190935266b1a2bc2ec500008152815183519293921080612042575082518151115b1561205c57612052600580612cdd565b9550505050610ed1565b600580549088905560408051828152602081018a90527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9910160405180910390a15f98975050505050505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906120dc9033908590600401613945565b602060405180830381865afa1580156120f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061211b9190613968565b6121575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e79565b50565b5f60095f6121685f856110ec565b81526020019081526020015f209050919050565b805460ff166121575760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e79565b6121e2604051806060016040528060298152602001613b60602991396120aa565b8151815181158015906121f457508082145b6122305760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610e79565b5f5b82811015610db85783818151811061224c5761224c613983565b6020026020010151601f5f87848151811061226957612269613983565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20819055508481815181106122a6576122a6613983565b60200260200101516001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68583815181106122ea576122ea613983565b602002602001015160405161230191815260200190565b60405180910390a2600101612232565b612332604051806060016040528060298152602001613a66602991396120aa565b825182515f5b82811015612398575f5b8281101561238f5761238787838151811061235f5761235f613983565b602002602001015187838151811061237957612379613983565b602002602001015187612d54565b600101612342565b50600101612338565b505050505050565b5f546001600160a01b031633146123ea5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e79565b565b5f60095f6123fa86866110ec565b81526020019081526020015f20600501548280820361242b5760405162461bcd60e51b8152600401610e79906135f1565b6037546001600160601b03908116908716111561246657604051632db8671b60e11b81526001600160601b0387166004820152602401610e79565b5f60095f61247489896110ec565b81526020019081526020015f20905061248c8161217c565b670de0b6b3a76400008510156124d75760405162461bcd60e51b815260206004820152601060248201526f0d2dcc6cadce8d2ecca40784062ca62760831b6044820152606401610e79565b856001600160a01b0316876001600160601b03167fc1d7bc090f3a87255c2f4e56f66d1b7a49683d279f77921b1701aa5d733ef745836005015488604051612529929190918252602082015260400190565b60405180910390a3600581018590555f611d69565b6001600160a01b0381166121575760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610e79565b601c54158061259c5750601c5443105b156125a357565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156125ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126119190613997565b9050805f0361261e575050565b5f8061262c43601c54612df8565b90505f61263b601a5483612e31565b905080841061264c57809250612650565b8392505b601d54831015612661575050505050565b43601c55601b5461267f906001600160a01b03878116911685612e72565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156126fe575f80fd5b505af1158015612710573d5f803e3d5ffd5b505050505050505050565b61273c604051806060016040528060298152602001613ae8602991396120aa565b81518151811580159061274e57508082145b61278a5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610e79565b5f5b82811015610db8578381815181106127a6576127a6613983565b602002602001015160275f8784815181106127c3576127c3613983565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208190555084818151811061280057612800613983565b60200260200101516001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f885838151811061284457612844613983565b602002602001015160405161285b91815260200190565b60405180910390a260010161278c565b61288c604051806060016040528060238152602001613b11602391396120aa565b6015546001600160a01b038381169116146128ad576128ad610c688361215a565b6001600160a01b0382165f818152602d6020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b6004545f906001600160a01b039081169083908116820361293e5760405162461bcd60e51b8152600401610e799061363c565b6129466123a0565b61294f8461253e565b600480546001600160a01b038681166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e2290610ec49083908890613699565b5f6129ac8461253e565b6037546001600160601b0390811690861611156129e757604051632db8671b60e11b81526001600160601b0386166004820152602401610e79565b5f60095f6129f588886110ec565b81526020019081526020015f209050612a0d8161217c565b670de0b6b3a7640000841115612a3157612a2960066008612cdd565b91505061164e565b8315801590612aab57506004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa158015612a85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa99190613997565b155b15612abc57612a29600d6009612cdd565b670de0b6b3a7640000831115612ad857612a2960146019612cdd565b83831015612aec57612a296014601a612cdd565b6001810154848114612b4f576001820185905560408051828152602081018790526001600160a01b038816916001600160601b038a16917f0d1a615379dc62cec7bc63b7e313a07ed659918f4ad3720b3af8041b305146f2910160405180910390a35b6004820154848114612bb2576004830185905560408051828152602081018790526001600160a01b038916916001600160601b038b16917fc90f7b48c299a8d58b0b9e2756e27773c6fb1daab159af052d6c5b791bc7eef7910160405180910390a35b5f98975050505050505050565b5f612bc86123a0565b612bd18261253e565b603180546001600160a01b038481166001600160a01b03198316179092556040519116907fcb20dab7409e4fb972d9adccb39530520b226ce6940d85c9523a499b950b6ea390612c249083908690613699565b60405180910390a15f9392505050565b5f546001600160a01b031633148061211b5750336001600160a01b038216146121575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e79565b60185462010000900460ff16156123ea5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610e79565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836014811115612d1157612d11613628565b83601a811115612d2357612d23613628565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610f0857610f08613628565b612d60610c688461215a565b6001600160a01b0383165f9081526029602052604081208291846008811115612d8b57612d8b613628565b815260208101919091526040015f20805460ff1916911515919091179055816008811115612dbb57612dbb613628565b836001600160a01b03167f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d83604051610ccd911515815260200190565b5f610f088383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612ec9565b5f610f0883836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612ef7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612ec4908490612f50565b505050565b5f8184841115612eec5760405162461bcd60e51b8152600401610e7991906139ae565b50610f0583856139d4565b5f831580612f03575082155b15612f0f57505f610f08565b5f612f1a84866139e7565b905083612f2786836139fe565b148390612f475760405162461bcd60e51b8152600401610e7991906139ae565b50949350505050565b5f612fa4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130239092919063ffffffff16565b905080515f1480612fc4575080806020019051810190612fc49190613968565b612ec45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e79565b6060610f0584845f85855f80866001600160a01b031685876040516130489190613a1d565b5f6040518083038185875af1925050503d805f8114613082576040519150601f19603f3d011682016040523d82523d5f602084013e613087565b606091505b5091509150611d6987838387606083156131015782515f036130fa576001600160a01b0385163b6130fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e79565b508161164e565b61164e83838151156131165781518083602001fd5b8060405162461bcd60e51b8152600401610e7991906139ae565b6001600160a01b0381168114612157575f80fd5b5f60208284031215613154575f80fd5b8135610f0881613130565b5f8060408385031215613170575f80fd5b823561317b81613130565b9150602083013561318b81613130565b809150509250929050565b5f602082840312156131a6575f80fd5b5035919050565b8015158114612157575f80fd5b5f805f606084860312156131cc575f80fd5b83356131d781613130565b925060208401356131e781613130565b915060408401356131f7816131ad565b809150509250925092565b5f8083601f840112613212575f80fd5b50813567ffffffffffffffff811115613229575f80fd5b6020830191508360208260051b8501011115613243575f80fd5b9250929050565b5f805f806040858703121561325d575f80fd5b843567ffffffffffffffff80821115613274575f80fd5b61328088838901613202565b90965094506020870135915080821115613298575f80fd5b506132a587828801613202565b95989497509550505050565b5f805f805f606086880312156132c5575f80fd5b853567ffffffffffffffff808211156132dc575f80fd5b6132e889838a01613202565b90975095506020880135915080821115613300575f80fd5b5061330d88828901613202565b9094509250506040860135613321816131ad565b809150509295509295909350565b5f6020828403121561333f575f80fd5b8135610f08816131ad565b80356001600160601b0381168114613360575f80fd5b919050565b5f805f60608486031215613377575f80fd5b6133808461334a565b9250602084013561339081613130565b929592945050506040919091013590565b5f80604083850312156133b2575f80fd5b82356133bd81613130565b9150602083013561318b816131ad565b5f80604083850312156133de575f80fd5b6133bd8361334a565b5f80604083850312156133f8575f80fd5b61317b8361334a565b5f805f60608486031215613413575f80fd5b833561341e81613130565b95602085013595506040909401359392505050565b5f805f8060808587031215613446575f80fd5b61344f8561334a565b9350602085013561345f81613130565b93969395505050506040820135916060013590565b5f60208284031215613484575f80fd5b610f088261334a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6134cd606083018661348d565b931515602083015250901515604090910152919050565b5f80604083850312156134f5575f80fd5b823561350081613130565b946020939093013593505050565b5f805f60608486031215613520575f80fd5b6131d78461334a565b5f805f6040848603121561353b575f80fd5b6135448461334a565b9250602084013567ffffffffffffffff80821115613560575f80fd5b818601915086601f830112613573575f80fd5b813581811115613581575f80fd5b876020828501011115613592575f80fd5b6020830194508093505050509250925092565b5f805f606084860312156135b7575f80fd5b833561338081613130565b5f80604083850312156135d3575f80fd5b82356135de81613130565b915060208301356009811061318b575f80fd5b6020808252601e908201527f6f6c642076616c75652069732073616d65206173206e65772076616c75650000604082015260600190565b634e487b7160e01b5f52602160045260245ffd5b60208082526022908201527f6f6c6420616464726573732069732073616d65206173206e6577206164647265604082015261737360f01b606082015260800190565b5f6020828403121561368e575f80fd5b8151610f0881613130565b6001600160a01b0392831681529116602082015260400190565b600181811c908216806136c757607f821691505b6020821081036136e557634e487b7160e01b5f52602260045260245ffd5b50919050565b818382375f9101908152919050565b5f808354613707816136b3565b6001828116801561371f576001811461373457613760565b60ff1984168752821515830287019450613760565b875f526020805f205f5b858110156137575781548a82015290840190820161373e565b50505082870194505b50929695505050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f8085546137a5816136b3565b806040860152606060018084165f81146137c657600181146137e257613811565b60ff1985166060890152606084151560051b8901019550613811565b8a5f526020805f205f5b868110156138075781548b82018701529084019082016137ec565b8a01606001975050505b5050505050828103602084015261382981858761376c565b9695505050505050565b634e487b7160e01b5f52604160045260245ffd5b601f821115612ec457805f5260205f20601f840160051c8101602085101561386c5750805b601f840160051c820191505b81811015610db8575f8155600101613878565b67ffffffffffffffff8311156138a3576138a3613833565b6138b7836138b183546136b3565b83613847565b5f601f8411600181146138e8575f85156138d15750838201355b5f19600387901b1c1916600186901b178355610db8565b5f83815260208120601f198716915b8281101561391757868501358255602094850194600190920191016138f7565b5086821015613933575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b03831681526040602082018190525f90610f059083018461348d565b5f60208284031215613978575f80fd5b8151610f08816131ad565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156139a7575f80fd5b5051919050565b602081525f610f08602083018461348d565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c2057610c206139c0565b8082028115828204841417610c2057610c206139c0565b5f82613a1857634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f92019182525091905056fe5f736574466f726365644c69717569646174696f6e466f725573657228616464726573732c616464726573732c626f6f6c295f736574416374696f6e7350617573656428616464726573735b5d2c75696e74385b5d2c626f6f6c297365744c69717569646174696f6e496e63656e746976652875696e7439362c616464726573732c75696e743235362973657457686974654c697374466c6173684c6f616e4163636f756e7428616464726573732c626f6f6c295f7365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d295f736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c29736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e74323536295f7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d29736574416c6c6f77436f7265506f6f6c46616c6c6261636b2875696e7439362c626f6f6c29736574436f6c6c61746572616c466163746f722875696e7439362c616464726573732c75696e743235362c75696e74323536297365744c69717569646174696f6e496e63656e7469766528616464726573732c75696e74323536297365744973426f72726f77416c6c6f7765642875696e7439362c616464726573732c626f6f6c29a2646970667358221220cf038a1331c74b44126bd686f279b2fb27270f9540f7616c7f5746a18eab0c8264736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106104bc575f3560e01c80637fb8e8cd11610279578063bec04f7211610156578063dce15449116100ca578063e87554461161008f578063e875544614610b9f578063f445d70314610ba8578063f519fc3014610bd5578063f851a44014610be8578063fa6331d814610bfa578063fd51a3ad14610c03575f80fd5b8063dce1544914610b0d578063dcfbc0c714610b20578063e0f6123d14610b33578063e37d4b7914610b55578063e85a296014610b8c575f80fd5b8063c7ee005e1161011b578063c7ee005e14610aba578063d136af441461072a578063d24febad14610acd578063d3270f9914610ae0578063d463654c14610af3578063d6ad5c3914610afa575f80fd5b8063bec04f7214610a5f578063bf32442d14610a68578063c32094c7146108e9578063c5b4db5514610a79578063c5f956af14610aa7575f80fd5b80639bd8f6e8116101ed578063b2eafc39116101b2578063b2eafc3914610999578063b8324c7c146109ac578063b88d846b14610a07578063bb82aa5e14610a1a578063bb85745014610a2d578063bbb8864a14610a40575f80fd5b80639bd8f6e81461093a5780639bf34cbb1461094d5780639cfdd9e614610960578063a657e57914610973578063a89766dd14610986575f80fd5b8063919a37361161023e578063919a3736146108c35780639254f5e5146108d65780639460c8b5146108e957806394b2294b146108fc57806396c99064146109055780639bb27d6214610927575f80fd5b80637fb8e8cd146108625780638a7dc1651461086f5780638b3113f61461073d5780638c1ac18a1461088e5780639159b177146108b0575f80fd5b806342adb211116103a75780635cc4fdeb1161031b578063719f701b116102e0578063719f701b146107ce57806373769099146107d757806376551383146108175780637938146f146108295780637d172bd51461083c5780637dc0d1d01461084f575f80fd5b80635cc4fdeb146107765780635dd3fc9d146107895780635f5af1aa146107a8578063607ef6c1146105935780636662c7c9146107bb575f80fd5b80634ef233fc1161036c5780634ef233fc1461071757806351a485e41461072a578063522c656b1461073d57806352d84d1e14610750578063530e784f1461076357806355ee1fe114610763575f80fd5b806342adb211146106ac5780634964f48c146106bf5780634a584432146106d25780634d99c776146106f15780634e0853db14610704575f80fd5b806324aaa2201161043e5780632ec04124116104035780632ec041241461063c578063317b0b771461056b578063354392401461064f5780634088c73e1461066257806341a18d2c1461066f578063425fad5814610699575f80fd5b806324aaa220146105e457806326782247146105f75780632a6a60651461060a5780632b5d790c146105e45780632bc7e29e1461061d575f80fd5b806312348e961161048457806312348e961461056b57806317db21631461057e578063186db48f1461059357806321af4569146105a657806324a3d622146105d1575f80fd5b806302c3bcbb146104c057806304ef9d58146104f257806308e0225c146104fb5780630db4b4e51461052557806310b983381461052e575b5f80fd5b6104df6104ce366004613144565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6104df60225481565b6104df61050936600461315f565b601360209081525f928352604080842090915290825290205481565b6104df601d5481565b61055b61053c36600461315f565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016104e9565b6104df610579366004613196565b610c16565b61059161058c3660046131ba565b610c26565b005b6105916105a136600461324a565b610cda565b601e546105b9906001600160a01b031681565b6040516001600160a01b0390911681526020016104e9565b600a546105b9906001600160a01b031681565b6105916105f23660046132b1565b610d4b565b6001546105b9906001600160a01b031681565b61055b61061836600461332f565b610dbf565b6104df61062b366004613144565b60166020525f908152604090205481565b6104df61064a366004613196565b610e55565b6104df61065d366004613365565b610ed8565b60185461055b9060ff1681565b6104df61067d36600461315f565b601260209081525f928352604080842090915290825290205481565b60185461055b9062010000900460ff1681565b6105916106ba3660046133a1565b610f0f565b6105916106cd3660046133cd565b610fb7565b6104df6106e0366004613144565b601f6020525f908152604090205481565b6104df6106ff3660046133e7565b6110ec565b610591610712366004613401565b611109565b610591610725366004613144565b6111cc565b61059161073836600461324a565b6112fa565b61059161074b3660046133a1565b611365565b6105b961075e366004613196565b611373565b6104df610771366004613144565b61139b565b6104df610784366004613401565b6113a5565b6104df610797366004613144565b602b6020525f908152604090205481565b6104df6107b6366004613144565b6113d3565b6105916107c9366004613196565b61146a565b6104df601c5481565b6107ff6107e5366004613144565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016104e9565b60185461055b90610100900460ff1681565b6105916108373660046133cd565b6114f6565b601b546105b9906001600160a01b031681565b6004546105b9906001600160a01b031681565b60395461055b9060ff1681565b6104df61087d366004613144565b60146020525f908152604090205481565b61055b61089c366004613144565b602d6020525f908152604090205460ff1681565b6104df6108be366004613433565b61161d565b6105916108d1366004613144565b611656565b6015546105b9906001600160a01b031681565b6104df6108f7366004613144565b6116c2565b6104df60075481565b610918610913366004613474565b6116cc565b6040516104e9939291906134bb565b6025546105b9906001600160a01b031681565b6104df6109483660046134e4565b611779565b6104df61095b366004613144565b6117a6565b6104df61096e366004613144565b61183c565b6037546107ff906001600160601b031681565b61059161099436600461350e565b6118d3565b6020546105b9906001600160a01b031681565b6109e36109ba366004613144565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104e9565b610591610a15366004613529565b611a14565b6002546105b9906001600160a01b031681565b610591610a3b366004613144565b611b78565b6104df610a4e366004613144565b602a6020525f908152604090205481565b6104df60175481565b6033546001600160a01b03166105b9565b610a8f6ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b0390911681526020016104e9565b6021546105b9906001600160a01b031681565b6031546105b9906001600160a01b031681565b6104df610adb3660046135a5565b611c0d565b6026546105b9906001600160a01b031681565b6107ff5f81565b610591610b0836600461332f565b611d74565b6105b9610b1b3660046134e4565b611e1d565b6003546105b9906001600160a01b031681565b61055b610b41366004613144565b60386020525f908152604090205460ff1681565b6109e3610b63366004613144565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61055b610b9a3660046135c2565b611e51565b6104df60055481565b61055b610bb636600461315f565b603260209081525f928352604080842090915290825290205460ff1681565b6104df610be3366004613144565b611e95565b5f546105b9906001600160a01b031681565b6104df601a5481565b6104df610c113660046134e4565b611f2c565b5f610c2082611fd0565b92915050565b610c47604051806060016040528060328152602001613a34603291396120aa565b6015546001600160a01b03838116911614610c6d57610c6d610c688361215a565b61217c565b6001600160a01b038381165f81815260326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fc080966e9e93529edc1b244180c245bc60f3d86f1e690a17651a5e428746a8cd91015b60405180910390a3505050565b610d458484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f920191909152506121c192505050565b50505050565b610db88585808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284375f92019190915250869250612311915050565b5050505050565b5f610dfe6040518060400160405280601881526020017f5f73657450726f746f636f6c50617573656428626f6f6c2900000000000000008152506120aa565b60188054831515620100000262ff0000199091161790556040517fd7500633dd3ddd74daa7af62f8c8404c7fe4a81da179998db851696bed004b3890610e4990841515815260200190565b60405180910390a15090565b5f60175482808203610e825760405162461bcd60e51b8152600401610e79906135f1565b60405180910390fd5b610e8a6123a0565b601780549085905560408051828152602081018790527f73747d68b346dce1e932bcd238282e7ac84c01569e1f8d0469c222fdc6e9d5a491015b60405180910390a15f9350505b5050919050565b5f610efa6040518060600160405280602f8152602001613a8f602f91396120aa565b610f058484846123ec565b90505b9392505050565b610f306040518060600160405280602a8152602001613abe602a91396120aa565b610f398261253e565b6001600160a01b0382165f9081526038602052604090205481151560ff909116151503610f64575050565b6001600160a01b0382165f81815260386020526040808220805460ff191685151590811790915590519092917f1f4df5032f431b9890646a781be28b0d693e581666d1a80be27ae3959069172291a35050565b610ff56040518060400160405280601a81526020017f736574506f6f6c4163746976652875696e7439362c626f6f6c290000000000008152506120aa565b6037546001600160601b03908116908316111561103057604051632db8671b60e11b81526001600160601b0383166004820152602401610e79565b6001600160601b03821661105757604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151560ff90911615150361108757505050565b60028101546040805160ff9092161515825283151560208301526001600160601b038516917f75e42fceb039532886a9d75717e843bfef67fd7f6f91f0fc5b1d48e9ce8a1ba9910160405180910390a2600201805460ff191691151591909117905550565b6001600160a01b031660a09190911b6001600160a01b0319161790565b601b546001600160a01b039081169084908116820361113a5760405162461bcd60e51b8152600401610e799061363c565b6111426123a0565b61114b8561253e565b601b546001600160a01b0316156111645761116461258c565b601b80546001600160a01b0319166001600160a01b038716908117909155601c859055601d84905560408051868152602081018690527f7059037d74ee16b0fb06a4a30f3348dd2635f301f92e373c92899a25a522ef6e910160405180910390a25050505050565b6111d46123a0565b6111dd8161253e565b5f816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561121a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061123e919061367e565b6033549091506001600160a01b0380831691161461129e5760405162461bcd60e51b815260206004820152601a60248201527f696e76616c6964207876732076746f6b656e20616464726573730000000000006044820152606401610e79565b6034546040516001600160a01b038085169216907f2565e1579c0926afb7113edbfd85373e85cadaa3e0346f04de19686a2bb86ed1905f90a350603480546001600160a01b0319166001600160a01b0392909216919091179055565b610d458484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f9201919091525061271b92505050565b61136f828261286b565b5050565b600d8181548110611382575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610c208261290b565b5f6113c76040518060600160405280602c8152602001613b34602c91396120aa565b610f055f8585856129a2565b600a545f906001600160a01b03908116908390811682036114065760405162461bcd60e51b8152600401610e799061363c565b61140e6123a0565b6114178461253e565b600a80546001600160a01b038681166001600160a01b03198316179092556040519116907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90610ec49083908890613699565b601a548180820361148d5760405162461bcd60e51b8152600401610e79906135f1565b6114956123a0565b601b546001600160a01b0316156114ae576114ae61258c565b601a80549084905560408051828152602081018690527fe81d4ac15e5afa1e708e66664eddc697177423d950d133bda8262d8885e6da3b91015b60405180910390a150505050565b611517604051806060016040528060258152602001613b89602591396120aa565b6037546001600160601b03908116908316111561155257604051632db8671b60e11b81526001600160601b0383166004820152602401610e79565b6001600160601b03821661157957604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151561010090910460ff161515036115ad57505050565b60028101546040805161010090920460ff161515825283151560208301526001600160601b038516917f9d2a9183b06e3492f91d3d88ae222e700c8873dd0068f9c3fc783eccb96a1ec4910160405180910390a260020180549115156101000261ff001990921691909117905550565b5f61163f604051806060016040528060338152602001613bae603391396120aa565b61164b858585856129a2565b90505b949350505050565b61165e6123a0565b6116678161253e565b6033546040516001600160a01b038084169216907ffe7fd0d872def0f65050e9f38fc6691d0c192c694a56f09b04bec5fb2ea61f2b905f90a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5f610c2082612bbf565b60366020525f90815260409020805481906116e6906136b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611712906136b3565b801561175d5780601f106117345761010080835404028352916020019161175d565b820191905f5260205f20905b81548152906001019060200180831161174057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f61179b604051806060016040528060288152602001613be1602891396120aa565b610f085f84846123ec565b6026545f906001600160a01b03908116908390811682036117d95760405162461bcd60e51b8152600401610e799061363c565b6117e16123a0565b6117ea8461253e565b602680546001600160a01b038681166001600160a01b0319831681179093556040519116917f0f7eb572d1b3053a0a3a33c04151364cf88d163182a5e4e1088cb8e52321e08a91610ec4918491613699565b6015545f906001600160a01b039081169083908116820361186f5760405162461bcd60e51b8152600401610e799061363c565b6118776123a0565b6118808461253e565b601580546001600160a01b038681166001600160a01b03198316179092556040519116907fe1ddcb2dab8e5b03cfc8c67a0d5861d91d16f7bd2612fd381faf4541d212c9b290610ec49083908890613699565b6118f4604051806060016040528060278152602001613c09602791396120aa565b6037546001600160601b03908116908416111561192f57604051632db8671b60e11b81526001600160601b0384166004820152602401610e79565b5f61193a84846110ec565b5f81815260096020526040902080549192509060ff1661196d57604051630665210960e21b815260040160405180910390fd5b82151581600601600c9054906101000a900460ff16151503611990575050505050565b600681015460408051600160601b90920460ff161515825284151560208301526001600160a01b038616916001600160601b038816917fe40f9c4af130bdb5bd1650ab4bc918dba9d900fa94685f0113e72a6cfe6c5fcc910160405180910390a36006018054921515600160601b0260ff60601b1990931692909217909155505050565b611a526040518060400160405280601b81526020017f736574506f6f6c4c6162656c2875696e7439362c737472696e672900000000008152506120aa565b6037546001600160601b039081169084161115611a8d57604051632db8671b60e11b81526001600160601b0384166004820152602401610e79565b6001600160601b038316611ab457604051630203217b60e61b815260040160405180910390fd5b5f819003611ad55760405163522e397360e11b815260040160405180910390fd5b6001600160601b0383165f90815260366020526040908190209051611afd90849084906136eb565b60405190819003812090611b129083906136fa565b604051809103902003611b255750505050565b836001600160601b03167f1ebc260ee8077871ff0b70b184ff9dac4ecee8b0f7dcc4f3a3f5068549f5078e825f018585604051611b6493929190613794565b60405180910390a280610db883858361388b565b6025546001600160a01b0390811690829081168203611ba95760405162461bcd60e51b8152600401610e799061363c565b611bb16123a0565b611bba8361253e565b602580546001600160a01b038581166001600160a01b03198316179092556040519116907fa5ea5616d5f6dbbaa62fdfcf3856723216eed485c394d9e51ec8e6d40e1d1ac1906114e89083908790613699565b6020545f90611c24906001600160a01b0316612c34565b670de0b6b3a76400008210611c6d5760405162461bcd60e51b815260206004820152600f60248201526e70657263656e74203e3d203130302560881b6044820152606401610e79565b611c768461253e565b611c7f8361253e565b6020805460218054602280546001600160a01b03198086166001600160a01b038c8116919091179097558316898716179093558690556040519284169316917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e890611ced9085908a90613699565b60405180910390a17f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac8287604051611d26929190613699565b60405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a15f5b979650505050505050565b611db26040518060400160405280601881526020017f736574466c6173684c6f616e50617573656428626f6f6c2900000000000000008152506120aa565b60395481151560ff909116151503611dc75750565b6039546040805160ff9092161515825282151560208301527f79bcfb2700d56371c7684799f99d64cbcd91f1e360f8048a42c9ba534be7c0a8910160405180910390a16039805460ff1916911515919091179055565b6008602052815f5260405f208181548110611e36575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611e7b57611e7b613628565b815260208101919091526040015f205460ff169392505050565b6028545f906001600160a01b0390811690839081168203611ec85760405162461bcd60e51b8152600401610e799061363c565b611ed06123a0565b611ed98461253e565b602880546001600160a01b038681166001600160a01b03198316179092556040519116907f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd490610ec49083908890613699565b5f611f35612c8f565b60185460ff16158015611f505750601854610100900460ff16155b611f8c5760405162461bcd60e51b815260206004820152600d60248201526c159052481a5cc81c185d5cd959609a1b6044820152606401610e79565b6015546001600160a01b03163314611fb157611faa600e6016612cdd565b9050610c20565b6001600160a01b0383165f908152601660205260408120839055610f08565b5f60055482808203611ff45760405162461bcd60e51b8152600401610e79906135f1565b611ffc6123a0565b604080516020808201835286825282518082018452670c7d713b49da00008152835191820190935266b1a2bc2ec500008152815183519293921080612042575082518151115b1561205c57612052600580612cdd565b9550505050610ed1565b600580549088905560408051828152602081018a90527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9910160405180910390a15f98975050505050505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906120dc9033908590600401613945565b602060405180830381865afa1580156120f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061211b9190613968565b6121575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e79565b50565b5f60095f6121685f856110ec565b81526020019081526020015f209050919050565b805460ff166121575760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610e79565b6121e2604051806060016040528060298152602001613b60602991396120aa565b8151815181158015906121f457508082145b6122305760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610e79565b5f5b82811015610db85783818151811061224c5761224c613983565b6020026020010151601f5f87848151811061226957612269613983565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20819055508481815181106122a6576122a6613983565b60200260200101516001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68583815181106122ea576122ea613983565b602002602001015160405161230191815260200190565b60405180910390a2600101612232565b612332604051806060016040528060298152602001613a66602991396120aa565b825182515f5b82811015612398575f5b8281101561238f5761238787838151811061235f5761235f613983565b602002602001015187838151811061237957612379613983565b602002602001015187612d54565b600101612342565b50600101612338565b505050505050565b5f546001600160a01b031633146123ea5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610e79565b565b5f60095f6123fa86866110ec565b81526020019081526020015f20600501548280820361242b5760405162461bcd60e51b8152600401610e79906135f1565b6037546001600160601b03908116908716111561246657604051632db8671b60e11b81526001600160601b0387166004820152602401610e79565b5f60095f61247489896110ec565b81526020019081526020015f20905061248c8161217c565b670de0b6b3a76400008510156124d75760405162461bcd60e51b815260206004820152601060248201526f0d2dcc6cadce8d2ecca40784062ca62760831b6044820152606401610e79565b856001600160a01b0316876001600160601b03167fc1d7bc090f3a87255c2f4e56f66d1b7a49683d279f77921b1701aa5d733ef745836005015488604051612529929190918252602082015260400190565b60405180910390a3600581018590555f611d69565b6001600160a01b0381166121575760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610e79565b601c54158061259c5750601c5443105b156125a357565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156125ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126119190613997565b9050805f0361261e575050565b5f8061262c43601c54612df8565b90505f61263b601a5483612e31565b905080841061264c57809250612650565b8392505b601d54831015612661575050505050565b43601c55601b5461267f906001600160a01b03878116911685612e72565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156126fe575f80fd5b505af1158015612710573d5f803e3d5ffd5b505050505050505050565b61273c604051806060016040528060298152602001613ae8602991396120aa565b81518151811580159061274e57508082145b61278a5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610e79565b5f5b82811015610db8578381815181106127a6576127a6613983565b602002602001015160275f8784815181106127c3576127c3613983565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208190555084818151811061280057612800613983565b60200260200101516001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f885838151811061284457612844613983565b602002602001015160405161285b91815260200190565b60405180910390a260010161278c565b61288c604051806060016040528060238152602001613b11602391396120aa565b6015546001600160a01b038381169116146128ad576128ad610c688361215a565b6001600160a01b0382165f818152602d6020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b6004545f906001600160a01b039081169083908116820361293e5760405162461bcd60e51b8152600401610e799061363c565b6129466123a0565b61294f8461253e565b600480546001600160a01b038681166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e2290610ec49083908890613699565b5f6129ac8461253e565b6037546001600160601b0390811690861611156129e757604051632db8671b60e11b81526001600160601b0386166004820152602401610e79565b5f60095f6129f588886110ec565b81526020019081526020015f209050612a0d8161217c565b670de0b6b3a7640000841115612a3157612a2960066008612cdd565b91505061164e565b8315801590612aab57506004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa158015612a85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa99190613997565b155b15612abc57612a29600d6009612cdd565b670de0b6b3a7640000831115612ad857612a2960146019612cdd565b83831015612aec57612a296014601a612cdd565b6001810154848114612b4f576001820185905560408051828152602081018790526001600160a01b038816916001600160601b038a16917f0d1a615379dc62cec7bc63b7e313a07ed659918f4ad3720b3af8041b305146f2910160405180910390a35b6004820154848114612bb2576004830185905560408051828152602081018790526001600160a01b038916916001600160601b038b16917fc90f7b48c299a8d58b0b9e2756e27773c6fb1daab159af052d6c5b791bc7eef7910160405180910390a35b5f98975050505050505050565b5f612bc86123a0565b612bd18261253e565b603180546001600160a01b038481166001600160a01b03198316179092556040519116907fcb20dab7409e4fb972d9adccb39530520b226ce6940d85c9523a499b950b6ea390612c249083908690613699565b60405180910390a15f9392505050565b5f546001600160a01b031633148061211b5750336001600160a01b038216146121575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610e79565b60185462010000900460ff16156123ea5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610e79565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836014811115612d1157612d11613628565b83601a811115612d2357612d23613628565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610f0857610f08613628565b612d60610c688461215a565b6001600160a01b0383165f9081526029602052604081208291846008811115612d8b57612d8b613628565b815260208101919091526040015f20805460ff1916911515919091179055816008811115612dbb57612dbb613628565b836001600160a01b03167f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d83604051610ccd911515815260200190565b5f610f088383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612ec9565b5f610f0883836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612ef7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612ec4908490612f50565b505050565b5f8184841115612eec5760405162461bcd60e51b8152600401610e7991906139ae565b50610f0583856139d4565b5f831580612f03575082155b15612f0f57505f610f08565b5f612f1a84866139e7565b905083612f2786836139fe565b148390612f475760405162461bcd60e51b8152600401610e7991906139ae565b50949350505050565b5f612fa4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166130239092919063ffffffff16565b905080515f1480612fc4575080806020019051810190612fc49190613968565b612ec45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610e79565b6060610f0584845f85855f80866001600160a01b031685876040516130489190613a1d565b5f6040518083038185875af1925050503d805f8114613082576040519150601f19603f3d011682016040523d82523d5f602084013e613087565b606091505b5091509150611d6987838387606083156131015782515f036130fa576001600160a01b0385163b6130fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610e79565b508161164e565b61164e83838151156131165781518083602001fd5b8060405162461bcd60e51b8152600401610e7991906139ae565b6001600160a01b0381168114612157575f80fd5b5f60208284031215613154575f80fd5b8135610f0881613130565b5f8060408385031215613170575f80fd5b823561317b81613130565b9150602083013561318b81613130565b809150509250929050565b5f602082840312156131a6575f80fd5b5035919050565b8015158114612157575f80fd5b5f805f606084860312156131cc575f80fd5b83356131d781613130565b925060208401356131e781613130565b915060408401356131f7816131ad565b809150509250925092565b5f8083601f840112613212575f80fd5b50813567ffffffffffffffff811115613229575f80fd5b6020830191508360208260051b8501011115613243575f80fd5b9250929050565b5f805f806040858703121561325d575f80fd5b843567ffffffffffffffff80821115613274575f80fd5b61328088838901613202565b90965094506020870135915080821115613298575f80fd5b506132a587828801613202565b95989497509550505050565b5f805f805f606086880312156132c5575f80fd5b853567ffffffffffffffff808211156132dc575f80fd5b6132e889838a01613202565b90975095506020880135915080821115613300575f80fd5b5061330d88828901613202565b9094509250506040860135613321816131ad565b809150509295509295909350565b5f6020828403121561333f575f80fd5b8135610f08816131ad565b80356001600160601b0381168114613360575f80fd5b919050565b5f805f60608486031215613377575f80fd5b6133808461334a565b9250602084013561339081613130565b929592945050506040919091013590565b5f80604083850312156133b2575f80fd5b82356133bd81613130565b9150602083013561318b816131ad565b5f80604083850312156133de575f80fd5b6133bd8361334a565b5f80604083850312156133f8575f80fd5b61317b8361334a565b5f805f60608486031215613413575f80fd5b833561341e81613130565b95602085013595506040909401359392505050565b5f805f8060808587031215613446575f80fd5b61344f8561334a565b9350602085013561345f81613130565b93969395505050506040820135916060013590565b5f60208284031215613484575f80fd5b610f088261334a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6134cd606083018661348d565b931515602083015250901515604090910152919050565b5f80604083850312156134f5575f80fd5b823561350081613130565b946020939093013593505050565b5f805f60608486031215613520575f80fd5b6131d78461334a565b5f805f6040848603121561353b575f80fd5b6135448461334a565b9250602084013567ffffffffffffffff80821115613560575f80fd5b818601915086601f830112613573575f80fd5b813581811115613581575f80fd5b876020828501011115613592575f80fd5b6020830194508093505050509250925092565b5f805f606084860312156135b7575f80fd5b833561338081613130565b5f80604083850312156135d3575f80fd5b82356135de81613130565b915060208301356009811061318b575f80fd5b6020808252601e908201527f6f6c642076616c75652069732073616d65206173206e65772076616c75650000604082015260600190565b634e487b7160e01b5f52602160045260245ffd5b60208082526022908201527f6f6c6420616464726573732069732073616d65206173206e6577206164647265604082015261737360f01b606082015260800190565b5f6020828403121561368e575f80fd5b8151610f0881613130565b6001600160a01b0392831681529116602082015260400190565b600181811c908216806136c757607f821691505b6020821081036136e557634e487b7160e01b5f52602260045260245ffd5b50919050565b818382375f9101908152919050565b5f808354613707816136b3565b6001828116801561371f576001811461373457613760565b60ff1984168752821515830287019450613760565b875f526020805f205f5b858110156137575781548a82015290840190820161373e565b50505082870194505b50929695505050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f8085546137a5816136b3565b806040860152606060018084165f81146137c657600181146137e257613811565b60ff1985166060890152606084151560051b8901019550613811565b8a5f526020805f205f5b868110156138075781548b82018701529084019082016137ec565b8a01606001975050505b5050505050828103602084015261382981858761376c565b9695505050505050565b634e487b7160e01b5f52604160045260245ffd5b601f821115612ec457805f5260205f20601f840160051c8101602085101561386c5750805b601f840160051c820191505b81811015610db8575f8155600101613878565b67ffffffffffffffff8311156138a3576138a3613833565b6138b7836138b183546136b3565b83613847565b5f601f8411600181146138e8575f85156138d15750838201355b5f19600387901b1c1916600186901b178355610db8565b5f83815260208120601f198716915b8281101561391757868501358255602094850194600190920191016138f7565b5086821015613933575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b03831681526040602082018190525f90610f059083018461348d565b5f60208284031215613978575f80fd5b8151610f08816131ad565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156139a7575f80fd5b5051919050565b602081525f610f08602083018461348d565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c2057610c206139c0565b8082028115828204841417610c2057610c206139c0565b5f82613a1857634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f92019182525091905056fe5f736574466f726365644c69717569646174696f6e466f725573657228616464726573732c616464726573732c626f6f6c295f736574416374696f6e7350617573656428616464726573735b5d2c75696e74385b5d2c626f6f6c297365744c69717569646174696f6e496e63656e746976652875696e7439362c616464726573732c75696e743235362973657457686974654c697374466c6173684c6f616e4163636f756e7428616464726573732c626f6f6c295f7365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d295f736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c29736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e74323536295f7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d29736574416c6c6f77436f7265506f6f6c46616c6c6261636b2875696e7439362c626f6f6c29736574436f6c6c61746572616c466163746f722875696e7439362c616464726573732c75696e743235362c75696e74323536297365744c69717569646174696f6e496e63656e7469766528616464726573732c75696e74323536297365744973426f72726f77416c6c6f7765642875696e7439362c616464726573732c626f6f6c29a2646970667358221220cf038a1331c74b44126bd686f279b2fb27270f9540f7616c7f5746a18eab0c8264736f6c63430008190033", + "numDeployments": 11, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"AlreadyInSelectedPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ArrayLengthMismatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"BorrowNotAllowedInPool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"EmptyPoolLabel\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ExecuteFlashLoanFailed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FailedToCreateDebtPosition\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanNotEnabled\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"FlashLoanPausedSystemWide\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"InactivePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"IncompatibleBorrowedAssets\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidAmount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidFlashLoanParams\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"InvalidOperationForCorePool\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"enum WeightFunction\",\"name\":\"strategy\",\"type\":\"uint8\"}],\"name\":\"InvalidWeightingStrategy\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"errorCode\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"shortfall\",\"type\":\"uint256\"}],\"name\":\"LiquidityCheckFailed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketAlreadyListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketConfigNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"MarketNotListed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"MarketNotListedInCorePool\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoAssetsRequested\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotAnApprovedDelegate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"repaid\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"required\",\"type\":\"uint256\"}],\"name\":\"NotEnoughRepayment\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"}],\"name\":\"PoolDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"PoolMarketNotFound\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"SenderNotAuthorizedForFlashLoan\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"requested\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximum\",\"type\":\"uint256\"}],\"name\":\"TooManyAssetsRequested\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"pauseState\",\"type\":\"bool\"}],\"name\":\"ActionPausedMarket\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"ActionProtocolPaused\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"BorrowAllowedUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DistributedVAIVaultVenus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldPaused\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newPaused\",\"type\":\"bool\"}],\"name\":\"FlashLoanPauseChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"bool\",\"name\":\"isWhitelisted\",\"type\":\"bool\"}],\"name\":\"IsAccountFlashLoanWhitelisted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledForUserUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"IsForcedLiquidationEnabledUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"MarketEntered\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"NewAccessControl\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBorrowCap\",\"type\":\"uint256\"}],\"name\":\"NewBorrowCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCloseFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCloseFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldCollateralFactorMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"NewCollateralFactor\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldComptrollerLens\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newComptrollerLens\",\"type\":\"address\"}],\"name\":\"NewComptrollerLens\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"oldDeviationBoundedOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"newDeviationBoundedOracle\",\"type\":\"address\"}],\"name\":\"NewDeviationBoundedOracle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationIncentiveMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationIncentive\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldLiquidationThresholdMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"NewLiquidationThreshold\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldLiquidatorContract\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newLiquidatorContract\",\"type\":\"address\"}],\"name\":\"NewLiquidatorContract\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPauseGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"NewPauseGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"oldPriceOracle\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newPriceOracle\",\"type\":\"address\"}],\"name\":\"NewPriceOracle\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract IPrime\",\"name\":\"oldPrimeToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract IPrime\",\"name\":\"newPrimeToken\",\"type\":\"address\"}],\"name\":\"NewPrimeToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newSupplyCap\",\"type\":\"uint256\"}],\"name\":\"NewSupplyCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"}],\"name\":\"NewTreasuryAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"}],\"name\":\"NewTreasuryGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldTreasuryPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"NewTreasuryPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract VAIControllerInterface\",\"name\":\"oldVAIController\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract VAIControllerInterface\",\"name\":\"newVAIController\",\"type\":\"address\"}],\"name\":\"NewVAIController\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldVAIMintRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVAIMintRate\",\"type\":\"uint256\"}],\"name\":\"NewVAIMintRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"vault_\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseStartBlock_\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"releaseInterval_\",\"type\":\"uint256\"}],\"name\":\"NewVAIVaultInfo\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldVenusVAIVaultRate\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newVenusVAIVaultRate\",\"type\":\"uint256\"}],\"name\":\"NewVenusVAIVaultRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldXVS\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newXVS\",\"type\":\"address\"}],\"name\":\"NewXVSToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"oldXVSVToken\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newXVSVToken\",\"type\":\"address\"}],\"name\":\"NewXVSVToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"PoolActiveStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"oldStatus\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newStatus\",\"type\":\"bool\"}],\"name\":\"PoolFallbackStatusUpdated\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"oldLabel\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"newLabel\",\"type\":\"string\"}],\"name\":\"PoolLabelUpdated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"_setAccessControl\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets_\",\"type\":\"address[]\"},{\"internalType\":\"enum Action[]\",\"name\":\"actions_\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}],\"name\":\"_setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"_setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"comptrollerLens_\",\"type\":\"address\"}],\"name\":\"_setComptrollerLens\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"_setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"_setForcedLiquidationForUser\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newLiquidatorContract_\",\"type\":\"address\"}],\"name\":\"_setLiquidatorContract\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"_setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newPauseGuardian\",\"type\":\"address\"}],\"name\":\"_setPauseGuardian\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"_setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_prime\",\"type\":\"address\"}],\"name\":\"_setPrimeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"state\",\"type\":\"bool\"}],\"name\":\"_setProtocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"_setTreasuryData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"vaiController_\",\"type\":\"address\"}],\"name\":\"_setVAIController\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newVAIMintRate\",\"type\":\"uint256\"}],\"name\":\"_setVAIMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vault_\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"releaseStartBlock_\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"minReleaseAmount_\",\"type\":\"uint256\"}],\"name\":\"_setVAIVaultInfo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"venusVAIVaultRate_\",\"type\":\"uint256\"}],\"name\":\"_setVenusVAIVaultRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"xvs_\",\"type\":\"address\"}],\"name\":\"_setXVSToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"xvsVToken_\",\"type\":\"address\"}],\"name\":\"_setXVSVToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"},{\"internalType\":\"enum Action\",\"name\":\"action\",\"type\":\"uint8\"}],\"name\":\"actionPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"corePoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getPoolMarketIndex\",\"outputs\":[{\"internalType\":\"PoolMarketId\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getXVSAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"markets_\",\"type\":\"address[]\"},{\"internalType\":\"enum Action[]\",\"name\":\"actions_\",\"type\":\"uint8[]\"},{\"internalType\":\"bool\",\"name\":\"paused_\",\"type\":\"bool\"}],\"name\":\"setActionsPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"allowFallback\",\"type\":\"bool\"}],\"name\":\"setAllowCorePoolFallback\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newCloseFactorMantissa\",\"type\":\"uint256\"}],\"name\":\"setCloseFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newCollateralFactorMantissa\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationThresholdMantissa\",\"type\":\"uint256\"}],\"name\":\"setCollateralFactor\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"newDeviationBoundedOracle\",\"type\":\"address\"}],\"name\":\"setDeviationBoundedOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"paused\",\"type\":\"bool\"}],\"name\":\"setFlashLoanPaused\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vTokenBorrowed\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"enable\",\"type\":\"bool\"}],\"name\":\"setForcedLiquidation\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"borrowAllowed\",\"type\":\"bool\"}],\"name\":\"setIsBorrowAllowed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vToken\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newLiquidationIncentiveMantissa\",\"type\":\"uint256\"}],\"name\":\"setLiquidationIncentive\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newBorrowCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketBorrowCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VToken[]\",\"name\":\"vTokens\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"newSupplyCaps\",\"type\":\"uint256[]\"}],\"name\":\"setMarketSupplyCaps\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"setMintedVAIOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"bool\",\"name\":\"active\",\"type\":\"bool\"}],\"name\":\"setPoolActive\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"poolId\",\"type\":\"uint96\"},{\"internalType\":\"string\",\"name\":\"newLabel\",\"type\":\"string\"}],\"name\":\"setPoolLabel\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"newOracle\",\"type\":\"address\"}],\"name\":\"setPriceOracle\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"_prime\",\"type\":\"address\"}],\"name\":\"setPrimeToken\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"isWhiteListed\",\"type\":\"bool\"}],\"name\":\"setWhiteListFlashLoanAccount\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusInitialIndex\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"\",\"type\":\"uint224\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"details\":\"This facet contains all the setters for the states\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setAccessControl(address)\":{\"details\":\"Allows the contract admin to set the address of access control of this contract\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"_setActionsPaused(address[],uint8[],bool)\":{\"details\":\"Allows a privileged role to pause/unpause the protocol action state\",\"params\":{\"actions_\":\"List of action ids to pause/unpause\",\"markets_\":\"Markets to pause/unpause the actions on\",\"paused_\":\"The new paused state (true=paused, false=unpaused)\"}},\"_setCloseFactor(uint256)\":{\"details\":\"Allows the contract admin to set the closeFactor used to liquidate borrows\",\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"_setComptrollerLens(address)\":{\"details\":\"Set ComptrollerLens contract address\",\"params\":{\"comptrollerLens_\":\"The new ComptrollerLens contract address to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setForcedLiquidation(address,bool)\":{\"details\":\"Allows a privileged role to set enable/disable forced liquidations\",\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"_setForcedLiquidationForUser(address,address,bool)\":{\"params\":{\"borrower\":\"The address of the borrower\",\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"_setLiquidatorContract(address)\":{\"details\":\"Allows the contract admin to update the address of liquidator contract\",\"params\":{\"newLiquidatorContract_\":\"The new address of the liquidator contract\"}},\"_setMarketBorrowCaps(address[],uint256[])\":{\"details\":\"Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\",\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"_setMarketSupplyCaps(address[],uint256[])\":{\"details\":\"Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\",\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"_setPauseGuardian(address)\":{\"details\":\"Allows the contract admin to change the Pause Guardian\",\"params\":{\"newPauseGuardian\":\"The address of the new Pause Guardian\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See enum Error for details)\"}},\"_setPriceOracle(address)\":{\"details\":\"Allows the contract admin to set a new price oracle used by the Comptroller\",\"params\":{\"newOracle\":\"The new price oracle to set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setPrimeToken(address)\":{\"params\":{\"_prime\":\"The new prime token contract to be set\"},\"returns\":{\"_0\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setProtocolPaused(bool)\":{\"details\":\"Allows a privileged role to pause/unpause protocol\",\"params\":{\"state\":\"The new state (true=paused, false=unpaused)\"},\"returns\":{\"_0\":\"bool The updated state of the protocol\"}},\"_setTreasuryData(address,address,uint256)\":{\"params\":{\"newTreasuryAddress\":\"The new address of the treasury to be set\",\"newTreasuryGuardian\":\"The new address of the treasury guardian to be set\",\"newTreasuryPercent\":\"The new treasury percent to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIController(address)\":{\"details\":\"Admin function to set a new VAI controller\",\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIMintRate(uint256)\":{\"params\":{\"newVAIMintRate\":\"The new VAI mint rate to be set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setVAIVaultInfo(address,uint256,uint256)\":{\"params\":{\"minReleaseAmount_\":\"The minimum release amount to VAI Vault\",\"releaseStartBlock_\":\"The start block of release to VAI Vault\",\"vault_\":\"The address of the VAI Vault\"}},\"_setVenusVAIVaultRate(uint256)\":{\"params\":{\"venusVAIVaultRate_\":\"The amount of XVS wei per block to distribute to VAI Vault\"}},\"_setXVSToken(address)\":{\"params\":{\"xvs_\":\"The address of the XVS token\"}},\"_setXVSVToken(address)\":{\"params\":{\"xvsVToken_\":\"The address of the XVS vToken\"}},\"actionPaused(address,uint8)\":{\"params\":{\"action\":\"Action id\",\"market\":\"vToken address\"}},\"getPoolMarketIndex(uint96,address)\":{\"details\":\"Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes, maintaining backward compatibility with legacy mappings - For other pools, packs the `poolId` and `market` address into a single `bytes32` key, The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\",\"params\":{\"poolId\":\"The ID of the pool\",\"vToken\":\"The address of the market (vToken)\"},\"returns\":{\"_0\":\"PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\"}},\"getXVSAddress()\":{\"returns\":{\"_0\":\"The address of XVS token\"}},\"setActionsPaused(address[],uint8[],bool)\":{\"params\":{\"actions_\":\"List of action ids to pause/unpause\",\"markets_\":\"Markets to pause/unpause the actions on\",\"paused_\":\"The new paused state (true=paused, false=unpaused)\"}},\"setAllowCorePoolFallback(uint96,bool)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.\",\"custom:event\":\"PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\",\"params\":{\"allowFallback\":\"True to allow fallback to Core Pool, false to disable.\",\"poolId\":\"ID of the pool to update.\"}},\"setCloseFactor(uint256)\":{\"params\":{\"newCloseFactorMantissa\":\"New close factor, scaled by 1e18\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise will revert\"}},\"setCollateralFactor(address,uint256,uint256)\":{\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"vToken\":\"The market to set the factor on\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setCollateralFactor(uint96,address,uint256,uint256)\":{\"params\":{\"newCollateralFactorMantissa\":\"The new collateral factor, scaled by 1e18\",\"newLiquidationThresholdMantissa\":\"The new liquidation threshold, scaled by 1e18\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The market to set the factor on\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setDeviationBoundedOracle(address)\":{\"params\":{\"newDeviationBoundedOracle\":\"The new DeviationBoundedOracle contract\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure\"}},\"setFlashLoanPaused(bool)\":{\"custom:access\":\"Only Governance\",\"custom:event\":\"Emits FlashLoanPauseChanged event\",\"params\":{\"paused\":\"True to pause flash loans, false to unpause\"}},\"setForcedLiquidation(address,bool)\":{\"params\":{\"enable\":\"Whether to enable forced liquidations\",\"vTokenBorrowed\":\"Borrowed vToken\"}},\"setIsBorrowAllowed(uint96,address,bool)\":{\"custom:error\":\"PoolDoesNotExist Reverts if the pool ID is invalid.MarketConfigNotFound Reverts if the market is not listed in the pool.\",\"custom:event\":\"BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\",\"params\":{\"borrowAllowed\":\"The new borrow allowed status.\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The address of the market (vToken).\"}},\"setLiquidationIncentive(address,uint256)\":{\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\",\"vToken\":\"The market to set the liquidationIncentive for\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setLiquidationIncentive(uint96,address,uint256)\":{\"params\":{\"newLiquidationIncentiveMantissa\":\"New liquidationIncentive scaled by 1e18\",\"poolId\":\"The ID of the pool.\",\"vToken\":\"The market to set the liquidationIncentive for\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure. (See ErrorReporter for details)\"}},\"setMarketBorrowCaps(address[],uint256[])\":{\"params\":{\"newBorrowCaps\":\"The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the borrow caps for\"}},\"setMarketSupplyCaps(address[],uint256[])\":{\"params\":{\"newSupplyCaps\":\"The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\",\"vTokens\":\"The addresses of the markets (tokens) to change the supply caps for\"}},\"setMintedVAIOf(address,uint256)\":{\"params\":{\"amount\":\"The amount of VAI to set to the account\",\"owner\":\"The address of the account to set\"},\"returns\":{\"_0\":\"The number of minted VAI by `owner`\"}},\"setPoolActive(uint96,bool)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.PoolDoesNotExist Reverts if the target pool ID does not exist.\",\"custom:event\":\"PoolActiveStatusUpdated Emitted after the pool active status is updated.\",\"params\":{\"active\":\"true to enable, false to disable\",\"poolId\":\"id of the pool to update\"}},\"setPoolLabel(uint96,string)\":{\"custom:error\":\"InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core PoolPoolDoesNotExist Reverts if the target pool ID does not existEmptyPoolLabel Reverts if the provided label is an empty string\",\"custom:event\":\"PoolLabelUpdated Emitted after the pool label is updated\",\"params\":{\"newLabel\":\"The new label for the pool\",\"poolId\":\"ID of the pool to update\"}},\"setPriceOracle(address)\":{\"params\":{\"newOracle\":\"The new price oracle to set\"},\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"setPrimeToken(address)\":{\"params\":{\"_prime\":\"The new prime token contract to be set\"},\"returns\":{\"_0\":\"uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"setWhiteListFlashLoanAccount(address,bool)\":{\"custom:event\":\"Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\",\"params\":{\"account\":\"The account to authorize for flash loans\",\"isWhiteListed\":\"True to whitelist the account for flash loans, false to remove from whitelist\"}}},\"title\":\"SetterFacet\",\"version\":1},\"userdoc\":{\"errors\":{\"AlreadyInSelectedPool()\":[{\"notice\":\"Thrown when You are already in the selected pool.\"}],\"ArrayLengthMismatch()\":[{\"notice\":\"Thrown when input array lengths do not match\"}],\"BorrowNotAllowedInPool()\":[{\"notice\":\"Thrown when borrowing is not allowed in the selected pool for a given market.\"}],\"EmptyPoolLabel()\":[{\"notice\":\"Thrown when the pool label is empty\"}],\"FlashLoanPausedSystemWide()\":[{\"notice\":\"Thrown when flash loans are paused system-wide\"}],\"InactivePool(uint96)\":[{\"notice\":\"Thrown when attempting to interact with an inactive pool\"}],\"IncompatibleBorrowedAssets()\":[{\"notice\":\"Thrown when One or more of your assets are not compatible with the selected pool.\"}],\"InvalidOperationForCorePool()\":[{\"notice\":\"Thrown when trying to call pool-specific methods on the Core Pool\"}],\"InvalidWeightingStrategy(uint8)\":[{\"notice\":\"Thrown when an invalid weighting strategy is provided\"}],\"LiquidityCheckFailed(uint256,uint256)\":[{\"notice\":\"Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\"}],\"MarketAlreadyListed(uint96,address)\":[{\"notice\":\"Thrown when a vToken is already listed in the specified pool\"}],\"MarketConfigNotFound()\":[{\"notice\":\"Thrown when market is not set in the _poolMarkets mapping\"}],\"MarketNotListed(address)\":[{\"notice\":\"Thrown when the vToken market is not listed\"}],\"MarketNotListedInCorePool()\":[{\"notice\":\"Thrown when market trying to add in a pool is not listed in the core pool\"}],\"NotEnoughRepayment(uint256,uint256)\":[{\"notice\":\"Thrown when repayment amount is insufficient to cover the fee\"}],\"PoolDoesNotExist(uint96)\":[{\"notice\":\"Thrown when a given pool ID does not exist\"}],\"PoolMarketNotFound(uint96,address)\":[{\"notice\":\"Thrown when trying to remove a market that is not listed in the given pool.\"}],\"TooManyAssetsRequested(uint256,uint256)\":[{\"notice\":\"Thrown when too many assets are requested in a single flash loan\"}]},\"events\":{\"ActionPausedMarket(address,uint8,bool)\":{\"notice\":\"Emitted when an action is paused on a market\"},\"ActionProtocolPaused(bool)\":{\"notice\":\"Emitted when protocol state is changed by admin\"},\"BorrowAllowedUpdated(uint96,address,bool,bool)\":{\"notice\":\"Emitted when the borrowAllowed flag is updated for a market\"},\"DistributedVAIVaultVenus(uint256)\":{\"notice\":\"Emitted when XVS is distributed to VAI Vault\"},\"FlashLoanPauseChanged(bool,bool)\":{\"notice\":\"Emitted when flash loan pause status changes\"},\"IsAccountFlashLoanWhitelisted(address,bool)\":{\"notice\":\"Emitted when an account's flash loan whitelist status is updated\"},\"IsForcedLiquidationEnabledForUserUpdated(address,address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\"},\"IsForcedLiquidationEnabledUpdated(address,bool)\":{\"notice\":\"Emitted when forced liquidation is enabled or disabled for all users in a market\"},\"MarketEntered(address,address)\":{\"notice\":\"Emitted when an account enters a market\"},\"NewAccessControl(address,address)\":{\"notice\":\"Emitted when access control address is changed by admin\"},\"NewBorrowCap(address,uint256)\":{\"notice\":\"Emitted when borrow cap for a vToken is changed\"},\"NewCloseFactor(uint256,uint256)\":{\"notice\":\"Emitted when close factor is changed by admin\"},\"NewCollateralFactor(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when a collateral factor for a market in a pool is changed by admin\"},\"NewComptrollerLens(address,address)\":{\"notice\":\"Emitted when ComptrollerLens address is changed\"},\"NewDeviationBoundedOracle(address,address)\":{\"notice\":\"Emitted when deviation bounded oracle is changed\"},\"NewLiquidationIncentive(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation incentive for a market in a pool is changed by admin\"},\"NewLiquidationThreshold(uint96,address,uint256,uint256)\":{\"notice\":\"Emitted when liquidation threshold for a market in a pool is changed by admin\"},\"NewLiquidatorContract(address,address)\":{\"notice\":\"Emitted when liquidator adress is changed\"},\"NewPauseGuardian(address,address)\":{\"notice\":\"Emitted when pause guardian is changed\"},\"NewPriceOracle(address,address)\":{\"notice\":\"Emitted when price oracle is changed\"},\"NewPrimeToken(address,address)\":{\"notice\":\"Emitted when prime token contract address is changed\"},\"NewSupplyCap(address,uint256)\":{\"notice\":\"Emitted when supply cap for a vToken is changed\"},\"NewTreasuryAddress(address,address)\":{\"notice\":\"Emitted when treasury address is changed\"},\"NewTreasuryGuardian(address,address)\":{\"notice\":\"Emitted when treasury guardian is changed\"},\"NewTreasuryPercent(uint256,uint256)\":{\"notice\":\"Emitted when treasury percent is changed\"},\"NewVAIController(address,address)\":{\"notice\":\"Emitted when VAIController is changed\"},\"NewVAIMintRate(uint256,uint256)\":{\"notice\":\"Emitted when VAI mint rate is changed by admin\"},\"NewVAIVaultInfo(address,uint256,uint256)\":{\"notice\":\"Emitted when VAI Vault info is changed\"},\"NewVenusVAIVaultRate(uint256,uint256)\":{\"notice\":\"Emitted when Venus VAI Vault rate is changed\"},\"NewXVSToken(address,address)\":{\"notice\":\"Emitted when XVS token address is changed\"},\"NewXVSVToken(address,address)\":{\"notice\":\"Emitted when XVS vToken address is changed\"},\"PoolActiveStatusUpdated(uint96,bool,bool)\":{\"notice\":\"Emitted when pool active status updated\"},\"PoolFallbackStatusUpdated(uint96,bool,bool)\":{\"notice\":\"Emitted when pool Fallback status is updated\"},\"PoolLabelUpdated(uint96,string,string)\":{\"notice\":\"Emitted when pool label is updated\"}},\"kind\":\"user\",\"methods\":{\"_setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"_setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Pause/unpause certain actions\"},\"_setCloseFactor(uint256)\":{\"notice\":\"Sets the closeFactor used when liquidating borrows\"},\"_setForcedLiquidation(address,bool)\":{\"notice\":\"Enables forced liquidations for a market. If forced liquidation is enabled, borrows in the market may be liquidated regardless of the account liquidity\"},\"_setForcedLiquidationForUser(address,address,bool)\":{\"notice\":\"Enables forced liquidations for user's borrows in a certain market. If forced liquidation is enabled, user's borrows in the market may be liquidated regardless of the account liquidity. Forced liquidation may be enabled for a user even if it is not enabled for the entire market.\"},\"_setLiquidatorContract(address)\":{\"notice\":\"Update the address of the liquidator contract\"},\"_setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\"},\"_setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\"},\"_setPauseGuardian(address)\":{\"notice\":\"Admin function to change the Pause Guardian\"},\"_setPriceOracle(address)\":{\"notice\":\"Sets a new price oracle for the comptroller\"},\"_setPrimeToken(address)\":{\"notice\":\"Sets the prime token contract for the comptroller\"},\"_setProtocolPaused(bool)\":{\"notice\":\"Set whole protocol pause/unpause state\"},\"_setTreasuryData(address,address,uint256)\":{\"notice\":\"Set the treasury data.\"},\"_setVAIController(address)\":{\"notice\":\"Sets a new VAI controller\"},\"_setVAIMintRate(uint256)\":{\"notice\":\"Set the VAI mint rate\"},\"_setVAIVaultInfo(address,uint256,uint256)\":{\"notice\":\"Set the VAI Vault infos\"},\"_setVenusVAIVaultRate(uint256)\":{\"notice\":\"Set the amount of XVS distributed per block to VAI Vault\"},\"_setXVSToken(address)\":{\"notice\":\"Set the address of the XVS token\"},\"_setXVSVToken(address)\":{\"notice\":\"Set the address of the XVS vToken\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"actionPaused(address,uint8)\":{\"notice\":\"Checks if a certain action is paused on a market\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"getPoolMarketIndex(uint96,address)\":{\"notice\":\"Returns the unique market index for the given poolId and vToken pair\"},\"getXVSAddress()\":{\"notice\":\"Returns the XVS address\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"setActionsPaused(address[],uint8[],bool)\":{\"notice\":\"Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\"},\"setAllowCorePoolFallback(uint96,bool)\":{\"notice\":\"Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\"},\"setCloseFactor(uint256)\":{\"notice\":\"Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\"},\"setCollateralFactor(address,uint256,uint256)\":{\"notice\":\"Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\"},\"setCollateralFactor(uint96,address,uint256,uint256)\":{\"notice\":\"Sets the collateral factor and liquidation threshold for a market in the specified pool.\"},\"setDeviationBoundedOracle(address)\":{\"notice\":\"Sets the DeviationBoundedOracle for conservative CF-path pricing\"},\"setFlashLoanPaused(bool)\":{\"notice\":\"Pause or unpause flash loans system-wide\"},\"setForcedLiquidation(address,bool)\":{\"notice\":\"Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\"},\"setIsBorrowAllowed(uint96,address,bool)\":{\"notice\":\"Updates the `isBorrowAllowed` flag for a market in a pool.\"},\"setLiquidationIncentive(address,uint256)\":{\"notice\":\"Sets the liquidation incentive for a market in the Core Pool only.\"},\"setLiquidationIncentive(uint96,address,uint256)\":{\"notice\":\"Sets the liquidation incentive for a market in the specified pool.\"},\"setMarketBorrowCaps(address[],uint256[])\":{\"notice\":\"Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\"},\"setMarketSupplyCaps(address[],uint256[])\":{\"notice\":\"Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\"},\"setMintedVAIOf(address,uint256)\":{\"notice\":\"Set the minted VAI amount of the `owner`\"},\"setPoolActive(uint96,bool)\":{\"notice\":\"updates active status for a specific pool (excluding the Core Pool)\"},\"setPoolLabel(uint96,string)\":{\"notice\":\"Updates the label for a specific pool (excluding the Core Pool)\"},\"setPriceOracle(address)\":{\"notice\":\"Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\"},\"setPrimeToken(address)\":{\"notice\":\"Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\"},\"setWhiteListFlashLoanAccount(address,bool)\":{\"notice\":\"Adds/Removes an account to the flash loan whitelist\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusInitialIndex()\":{\"notice\":\"The initial Venus index for a market\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This facet contract contains all the configurational setter functions\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/facets/SetterFacet.sol\":\"SetterFacet\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/FacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../../../Utils/ErrorReporter.sol\\\";\\nimport { ExponentialNoError } from \\\"../../../Utils/ExponentialNoError.sol\\\";\\nimport { IVAIVault, Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../../../Comptroller/ComptrollerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\nimport { IFacetBase, WeightFunction } from \\\"../interfaces/IFacetBase.sol\\\";\\n\\n/**\\n * @title FacetBase\\n * @author Venus\\n * @notice This facet contract contains functions related to access and checks\\n */\\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\\n using SafeERC20 for IERC20;\\n\\n /// @notice The initial Venus index for a market\\n uint224 public constant venusInitialIndex = 1e36;\\n // poolId for core Pool\\n uint96 public constant corePoolId = 0;\\n // closeFactorMantissa must be strictly greater than this value\\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\\n // closeFactorMantissa must not exceed this value\\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\\n\\n /// @notice Emitted when an account enters a market\\n event MarketEntered(VToken indexed vToken, address indexed account);\\n\\n /// @notice Emitted when XVS is distributed to VAI Vault\\n event DistributedVAIVaultVenus(uint256 amount);\\n\\n /// @notice Reverts if the protocol is paused\\n function checkProtocolPauseState() internal view {\\n require(!protocolPaused, \\\"protocol is paused\\\");\\n }\\n\\n /// @notice Reverts if a certain action is paused on a market\\n function checkActionPauseState(address market, Action action) internal view {\\n require(!actionPaused(market, action), \\\"action is paused\\\");\\n }\\n\\n /// @notice Reverts if the caller is not admin\\n function ensureAdmin() internal view {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n }\\n\\n /// @notice Checks the passed address is nonzero\\n function ensureNonzeroAddress(address someone) internal pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @notice Reverts if the market is not listed\\n function ensureListed(Market storage market) internal view {\\n require(market.isListed, \\\"market not listed\\\");\\n }\\n\\n /// @notice Reverts if the caller is neither admin nor the passed address\\n function ensureAdminOr(address privilegedAddress) internal view {\\n require(msg.sender == admin || msg.sender == privilegedAddress, \\\"access denied\\\");\\n }\\n\\n /// @notice Checks the caller is allowed to call the specified fuction\\n function ensureAllowed(string memory functionSig) internal view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) public view returns (bool) {\\n return _actionPaused[market][uint256(action)];\\n }\\n\\n /**\\n * @notice Get the latest block number\\n */\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n /**\\n * @notice Get the latest block number with the safe32 check\\n */\\n function getBlockNumberAsUint32() internal view returns (uint32) {\\n return safe32(getBlockNumber(), \\\"block # > 32 bits\\\");\\n }\\n\\n /**\\n * @notice Transfer XVS to VAI Vault\\n */\\n function releaseToVault() internal {\\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\\n return;\\n }\\n\\n IERC20 xvs_ = IERC20(xvs);\\n\\n uint256 xvsBalance = xvs_.balanceOf(address(this));\\n if (xvsBalance == 0) {\\n return;\\n }\\n\\n uint256 actualAmount;\\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\\n // releaseAmount = venusVAIVaultRate * deltaBlocks\\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\\n\\n if (xvsBalance >= releaseAmount_) {\\n actualAmount = releaseAmount_;\\n } else {\\n actualAmount = xvsBalance;\\n }\\n\\n if (actualAmount < minReleaseAmount) {\\n return;\\n }\\n\\n releaseStartBlock = getBlockNumber();\\n\\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\\n emit DistributedVAIVaultVenus(actualAmount);\\n\\n IVAIVault(vaiVaultAddress).updatePendingRewards();\\n }\\n\\n /**\\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\\n * exceeds the threshold.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternal(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal returns (Error, uint256, uint256) {\\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\\n // Required on the CF path so bounded prices are computed once and reused\\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\\n // within the same transaction.\\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\\n _updateProtectionStates(account);\\n }\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\\n * the transient cache. Use this only in external view functions where state mutation is not\\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\\n * was already executed earlier in the same transaction, the DBO transient cache will already be\\n * populated and this function will read from it gas-efficiently \\u2014 no recomputation occurs.\\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\\n * scratch on each call; results are still correct but cost more gas.\\n * @param account The account to determine liquidity for\\n * @param vTokenModify The market to hypothetically redeem/borrow in\\n * @param redeemTokens The number of vTokens to hypothetically redeem\\n * @param borrowAmount The amount of underlying to hypothetically borrow\\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\\n * @return err Possible error code\\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\\n */\\n function getHypotheticalAccountLiquidityInternalView(\\n address account,\\n VToken vTokenModify,\\n uint256 redeemTokens,\\n uint256 borrowAmount,\\n WeightFunction weightingStrategy\\n ) internal view returns (Error, uint256, uint256) {\\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\\n address(this),\\n account,\\n vTokenModify,\\n redeemTokens,\\n borrowAmount,\\n weightingStrategy\\n );\\n return (Error(err), liquidity, shortfall);\\n }\\n\\n /**\\n * @notice Add the market to the borrower's \\\"assets in\\\" for liquidity calculations\\n * @param vToken The market to enter\\n * @param borrower The address of the account to modify\\n * @return Success indicator for whether the market was entered\\n */\\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\\n ensureListed(marketToJoin);\\n if (marketToJoin.accountMembership[borrower]) {\\n // already joined\\n return Error.NO_ERROR;\\n }\\n // survived the gauntlet, add to list\\n // NOTE: we store these somewhat redundantly as a significant optimization\\n // this avoids having to iterate through the list for the most common use cases\\n // that is, only when we need to perform liquidity checks\\n // and not whenever we want to check if an account is in a particular market\\n marketToJoin.accountMembership[borrower] = true;\\n accountAssets[borrower].push(vToken);\\n\\n emit MarketEntered(vToken, borrower);\\n\\n return Error.NO_ERROR;\\n }\\n\\n /**\\n * @notice Checks for the user is allowed to redeem tokens\\n * @param vToken Address of the market\\n * @param redeemer Address of the user\\n * @param redeemTokens Amount of tokens to redeem\\n * @return Success indicator for redeem is allowed or not\\n */\\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\\n ensureListed(getCorePoolMarket(vToken));\\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\\n return uint256(Error.NO_ERROR);\\n }\\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\\n redeemer,\\n VToken(vToken),\\n redeemTokens,\\n 0,\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n if (err != Error.NO_ERROR) {\\n return uint256(err);\\n }\\n if (shortfall != 0) {\\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\\n }\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address) {\\n return xvs;\\n }\\n\\n /**\\n * @notice Returns the unique market index for the given poolId and vToken pair\\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\\n * maintaining backward compatibility with legacy mappings\\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\\n * @param poolId The ID of the pool\\n * @param vToken The address of the market (vToken)\\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\\n */\\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\\n }\\n\\n /**\\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\\n * @param vToken The vToken address for which the market details are requested\\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\\n */\\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\\n }\\n\\n /**\\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\\n * @param account The account whose collateral assets need protection state updates\\n */\\n function _updateProtectionStates(address account) internal {\\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\\n VToken[] memory assets = accountAssets[account];\\n uint256 len = assets.length;\\n for (uint256 i; i < len; ++i) {\\n boundedOracle.updateProtectionState(address(assets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x5d92d6069e4b000e570ee12047a4b57977ae5940e7dd0abab83e32bb844e9bf4\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/facets/SetterFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../../ComptrollerLensInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../../../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { IPrime } from \\\"../../../Tokens/Prime/IPrime.sol\\\";\\nimport { ISetterFacet } from \\\"../interfaces/ISetterFacet.sol\\\";\\nimport { FacetBase } from \\\"./FacetBase.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\n/**\\n * @title SetterFacet\\n * @author Venus\\n * @dev This facet contains all the setters for the states\\n * @notice This facet contract contains all the configurational setter functions\\n */\\ncontract SetterFacet is ISetterFacet, FacetBase {\\n /// @notice Emitted when close factor is changed by admin\\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\\n\\n /// @notice Emitted when a collateral factor for a market in a pool is changed by admin\\n event NewCollateralFactor(\\n uint96 indexed poolId,\\n VToken indexed vToken,\\n uint256 oldCollateralFactorMantissa,\\n uint256 newCollateralFactorMantissa\\n );\\n\\n /// @notice Emitted when liquidation incentive for a market in a pool is changed by admin\\n event NewLiquidationIncentive(\\n uint96 indexed poolId,\\n address indexed vToken,\\n uint256 oldLiquidationIncentiveMantissa,\\n uint256 newLiquidationIncentiveMantissa\\n );\\n\\n /// @notice Emitted when price oracle is changed\\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\\n\\n /// @notice Emitted when deviation bounded oracle is changed\\n event NewDeviationBoundedOracle(\\n IDeviationBoundedOracle oldDeviationBoundedOracle,\\n IDeviationBoundedOracle newDeviationBoundedOracle\\n );\\n\\n /// @notice Emitted when borrow cap for a vToken is changed\\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\\n\\n /// @notice Emitted when VAIController is changed\\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\\n\\n /// @notice Emitted when VAI mint rate is changed by admin\\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\\n\\n /// @notice Emitted when protocol state is changed by admin\\n event ActionProtocolPaused(bool state);\\n\\n /// @notice Emitted when treasury guardian is changed\\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\\n\\n /// @notice Emitted when treasury address is changed\\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\\n\\n /// @notice Emitted when treasury percent is changed\\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\\n\\n /// @notice Emitted when liquidator adress is changed\\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\\n\\n /// @notice Emitted when ComptrollerLens address is changed\\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\\n\\n /// @notice Emitted when supply cap for a vToken is changed\\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /// @notice Emitted when pause guardian is changed\\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\\n\\n /// @notice Emitted when an action is paused on a market\\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\\n\\n /// @notice Emitted when VAI Vault info is changed\\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\\n\\n /// @notice Emitted when Venus VAI Vault rate is changed\\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\\n\\n /// @notice Emitted when prime token contract address is changed\\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for all users in a market\\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\\n\\n /// @notice Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\\n event IsForcedLiquidationEnabledForUserUpdated(address indexed borrower, address indexed vToken, bool enable);\\n\\n /// @notice Emitted when XVS token address is changed\\n event NewXVSToken(address indexed oldXVS, address indexed newXVS);\\n\\n /// @notice Emitted when XVS vToken address is changed\\n event NewXVSVToken(address indexed oldXVSVToken, address indexed newXVSVToken);\\n\\n /// @notice Emitted when an account's flash loan whitelist status is updated\\n event IsAccountFlashLoanWhitelisted(address indexed account, bool indexed isWhitelisted);\\n\\n /// @notice Emitted when liquidation threshold for a market in a pool is changed by admin\\n event NewLiquidationThreshold(\\n uint96 indexed poolId,\\n VToken indexed vToken,\\n uint256 oldLiquidationThresholdMantissa,\\n uint256 newLiquidationThresholdMantissa\\n );\\n\\n /// @notice Emitted when the borrowAllowed flag is updated for a market\\n event BorrowAllowedUpdated(uint96 indexed poolId, address indexed market, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when pool active status updated\\n event PoolActiveStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when pool label is updated\\n event PoolLabelUpdated(uint96 indexed poolId, string oldLabel, string newLabel);\\n\\n /// @notice Emitted when pool Fallback status is updated\\n event PoolFallbackStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\\n\\n /// @notice Emitted when flash loan pause status changes\\n event FlashLoanPauseChanged(bool oldPaused, bool newPaused);\\n\\n /**\\n * @notice Compare two addresses to ensure they are different\\n * @param oldAddress The original address to compare\\n * @param newAddress The new address to compare\\n */\\n modifier compareAddress(address oldAddress, address newAddress) {\\n require(oldAddress != newAddress, \\\"old address is same as new address\\\");\\n _;\\n }\\n\\n /**\\n * @notice Compare two values to ensure they are different\\n * @param oldValue The original value to compare\\n * @param newValue The new value to compare\\n */\\n modifier compareValue(uint256 oldValue, uint256 newValue) {\\n require(oldValue != newValue, \\\"old value is same as new value\\\");\\n _;\\n }\\n\\n /**\\n * @notice Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\\n * @param newOracle The new price oracle to set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\\n return __setPriceOracle(newOracle);\\n }\\n\\n /**\\n * @notice Sets a new price oracle for the comptroller\\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\\n * @param newOracle The new price oracle to set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\\n return __setPriceOracle(newOracle);\\n }\\n\\n /**\\n * @notice Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint256 0=success, otherwise will revert\\n */\\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\\n return __setCloseFactor(newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the closeFactor used when liquidating borrows\\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\\n * @return uint256 0=success, otherwise will revert\\n */\\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\\n return __setCloseFactor(newCloseFactorMantissa);\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Allows the contract admin to set the address of access control of this contract\\n * @param newAccessControlAddress New address for the access control\\n * @return uint256 0=success, otherwise will revert\\n */\\n function _setAccessControl(\\n address newAccessControlAddress\\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(newAccessControlAddress);\\n\\n address oldAccessControlAddress = accessControl;\\n\\n accessControl = newAccessControlAddress;\\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setCollateralFactor(address,uint256,uint256)\\\");\\n return __setCollateralFactor(corePoolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\\n }\\n\\n /**\\n * @notice Sets the liquidation incentive for a market in the Core Pool only.\\n * @param vToken The market to set the liquidationIncentive for\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setLiquidationIncentive(\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setLiquidationIncentive(address,uint256)\\\");\\n return __setLiquidationIncentive(corePoolId, vToken, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Sets the collateral factor and liquidation threshold for a market in the specified pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setCollateralFactor(uint96,address,uint256,uint256)\\\");\\n return __setCollateralFactor(poolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\\n }\\n\\n /**\\n * @notice Sets the liquidation incentive for a market in the specified pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the liquidationIncentive for\\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\\n */\\n function setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setLiquidationIncentive(uint96,address,uint256)\\\");\\n return __setLiquidationIncentive(poolId, vToken, newLiquidationIncentiveMantissa);\\n }\\n\\n /**\\n * @notice Update the address of the liquidator contract\\n * @dev Allows the contract admin to update the address of liquidator contract\\n * @param newLiquidatorContract_ The new address of the liquidator contract\\n */\\n function _setLiquidatorContract(\\n address newLiquidatorContract_\\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(newLiquidatorContract_);\\n address oldLiquidatorContract = liquidatorContract;\\n liquidatorContract = newLiquidatorContract_;\\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\\n }\\n\\n /**\\n * @notice Admin function to change the Pause Guardian\\n * @dev Allows the contract admin to change the Pause Guardian\\n * @param newPauseGuardian The address of the new Pause Guardian\\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\\n */\\n function _setPauseGuardian(\\n address newPauseGuardian\\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\\n ensureAdmin();\\n ensureNonzeroAddress(newPauseGuardian);\\n\\n // Save current value for inclusion in log\\n address oldPauseGuardian = pauseGuardian;\\n // Store pauseGuardian with value newPauseGuardian\\n pauseGuardian = newPauseGuardian;\\n\\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\\n */\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\\n }\\n\\n /**\\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\\n */\\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\\n }\\n\\n /**\\n * @notice Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\\n */\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\\n }\\n\\n /**\\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\\n */\\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\\n }\\n\\n /**\\n * @notice Set whole protocol pause/unpause state\\n * @dev Allows a privileged role to pause/unpause protocol\\n * @param state The new state (true=paused, false=unpaused)\\n * @return bool The updated state of the protocol\\n */\\n function _setProtocolPaused(bool state) external returns (bool) {\\n ensureAllowed(\\\"_setProtocolPaused(bool)\\\");\\n\\n protocolPaused = state;\\n emit ActionProtocolPaused(state);\\n return state;\\n }\\n\\n /**\\n * @notice Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\\n * @param markets_ Markets to pause/unpause the actions on\\n * @param actions_ List of action ids to pause/unpause\\n * @param paused_ The new paused state (true=paused, false=unpaused)\\n */\\n function setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\\n __setActionsPaused(markets_, actions_, paused_);\\n }\\n\\n /**\\n * @notice Pause/unpause certain actions\\n * @dev Allows a privileged role to pause/unpause the protocol action state\\n * @param markets_ Markets to pause/unpause the actions on\\n * @param actions_ List of action ids to pause/unpause\\n * @param paused_ The new paused state (true=paused, false=unpaused)\\n */\\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\\n __setActionsPaused(markets_, actions_, paused_);\\n }\\n\\n /**\\n * @dev Pause/unpause an action on a market\\n * @param market Market to pause/unpause the action on\\n * @param action Action id to pause/unpause\\n * @param paused The new paused state (true=paused, false=unpaused)\\n */\\n function setActionPausedInternal(address market, Action action, bool paused) internal {\\n ensureListed(getCorePoolMarket(market));\\n _actionPaused[market][uint256(action)] = paused;\\n emit ActionPausedMarket(VToken(market), action, paused);\\n }\\n\\n /**\\n * @notice Sets a new VAI controller\\n * @dev Admin function to set a new VAI controller\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setVAIController(\\n VAIControllerInterface vaiController_\\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(address(vaiController_));\\n\\n VAIControllerInterface oldVaiController = vaiController;\\n vaiController = vaiController_;\\n emit NewVAIController(oldVaiController, vaiController_);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the VAI mint rate\\n * @param newVAIMintRate The new VAI mint rate to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setVAIMintRate(\\n uint256 newVAIMintRate\\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n uint256 oldVAIMintRate = vaiMintRate;\\n vaiMintRate = newVAIMintRate;\\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the minted VAI amount of the `owner`\\n * @param owner The address of the account to set\\n * @param amount The amount of VAI to set to the account\\n * @return The number of minted VAI by `owner`\\n */\\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\\n checkProtocolPauseState();\\n\\n // Pausing is a very serious situation - we revert to sound the alarms\\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \\\"VAI is paused\\\");\\n // Check caller is vaiController\\n if (msg.sender != address(vaiController)) {\\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\\n }\\n mintedVAIs[owner] = amount;\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the treasury data.\\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\\n * @param newTreasuryAddress The new address of the treasury to be set\\n * @param newTreasuryPercent The new treasury percent to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256) {\\n // Check caller is admin\\n ensureAdminOr(treasuryGuardian);\\n\\n require(newTreasuryPercent < 1e18, \\\"percent >= 100%\\\");\\n ensureNonzeroAddress(newTreasuryGuardian);\\n ensureNonzeroAddress(newTreasuryAddress);\\n\\n address oldTreasuryGuardian = treasuryGuardian;\\n address oldTreasuryAddress = treasuryAddress;\\n uint256 oldTreasuryPercent = treasuryPercent;\\n\\n treasuryGuardian = newTreasuryGuardian;\\n treasuryAddress = newTreasuryAddress;\\n treasuryPercent = newTreasuryPercent;\\n\\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /*** Venus Distribution ***/\\n\\n /**\\n * @dev Set ComptrollerLens contract address\\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptrollerLens(\\n ComptrollerLensInterface comptrollerLens_\\n ) external virtual compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\\n ensureAdmin();\\n ensureNonzeroAddress(address(comptrollerLens_));\\n address oldComptrollerLens = address(comptrollerLens);\\n comptrollerLens = comptrollerLens_;\\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the amount of XVS distributed per block to VAI Vault\\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\\n */\\n function _setVenusVAIVaultRate(\\n uint256 venusVAIVaultRate_\\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\\n ensureAdmin();\\n if (vaiVaultAddress != address(0)) {\\n releaseToVault();\\n }\\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\\n venusVAIVaultRate = venusVAIVaultRate_;\\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\\n }\\n\\n /**\\n * @notice Set the VAI Vault infos\\n * @param vault_ The address of the VAI Vault\\n * @param releaseStartBlock_ The start block of release to VAI Vault\\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\\n */\\n function _setVAIVaultInfo(\\n address vault_,\\n uint256 releaseStartBlock_,\\n uint256 minReleaseAmount_\\n ) external compareAddress(vaiVaultAddress, vault_) {\\n ensureAdmin();\\n ensureNonzeroAddress(vault_);\\n if (vaiVaultAddress != address(0)) {\\n releaseToVault();\\n }\\n\\n vaiVaultAddress = vault_;\\n releaseStartBlock = releaseStartBlock_;\\n minReleaseAmount = minReleaseAmount_;\\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\\n }\\n\\n /**\\n * @notice Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\\n * @param _prime The new prime token contract to be set\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function setPrimeToken(IPrime _prime) external returns (uint256) {\\n return __setPrimeToken(_prime);\\n }\\n\\n /**\\n * @notice Sets the prime token contract for the comptroller\\n * @param _prime The new prime token contract to be set\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPrimeToken(IPrime _prime) external returns (uint256) {\\n return __setPrimeToken(_prime);\\n }\\n\\n /**\\n * @notice Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n __setForcedLiquidation(vTokenBorrowed, enable);\\n }\\n\\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\\n * borrows in the market may be liquidated regardless of the account liquidity\\n * @dev Allows a privileged role to set enable/disable forced liquidations\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\\n __setForcedLiquidation(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Enables forced liquidations for user's borrows in a certain market. If forced\\n * liquidation is enabled, user's borrows in the market may be liquidated regardless of\\n * the account liquidity. Forced liquidation may be enabled for a user even if it is not\\n * enabled for the entire market.\\n * @param borrower The address of the borrower\\n * @param vTokenBorrowed Borrowed vToken\\n * @param enable Whether to enable forced liquidations\\n */\\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external {\\n ensureAllowed(\\\"_setForcedLiquidationForUser(address,address,bool)\\\");\\n if (vTokenBorrowed != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledForUserUpdated(borrower, vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @notice Set the address of the XVS token\\n * @param xvs_ The address of the XVS token\\n */\\n function _setXVSToken(address xvs_) external {\\n ensureAdmin();\\n ensureNonzeroAddress(xvs_);\\n\\n emit NewXVSToken(xvs, xvs_);\\n xvs = xvs_;\\n }\\n\\n /**\\n * @notice Set the address of the XVS vToken\\n * @param xvsVToken_ The address of the XVS vToken\\n */\\n function _setXVSVToken(address xvsVToken_) external {\\n ensureAdmin();\\n ensureNonzeroAddress(xvsVToken_);\\n\\n address underlying = VToken(xvsVToken_).underlying();\\n require(underlying == xvs, \\\"invalid xvs vtoken address\\\");\\n\\n emit NewXVSVToken(xvsVToken, xvsVToken_);\\n xvsVToken = xvsVToken_;\\n }\\n\\n /**\\n * @notice Adds/Removes an account to the flash loan whitelist\\n * @param account The account to authorize for flash loans\\n * @param isWhiteListed True to whitelist the account for flash loans, false to remove from whitelist\\n * @custom:event Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\\n */\\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external {\\n ensureAllowed(\\\"setWhiteListFlashLoanAccount(address,bool)\\\");\\n ensureNonzeroAddress(account);\\n\\n // If the account's status is already the same as the desired status, do nothing\\n if (authorizedFlashLoan[account] == isWhiteListed) {\\n return;\\n }\\n\\n authorizedFlashLoan[account] = isWhiteListed;\\n emit IsAccountFlashLoanWhitelisted(account, isWhiteListed);\\n }\\n\\n /**\\n * @notice Pause or unpause flash loans system-wide\\n * @param paused True to pause flash loans, false to unpause\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanPauseChanged event\\n */\\n function setFlashLoanPaused(bool paused) external {\\n ensureAllowed(\\\"setFlashLoanPaused(bool)\\\");\\n\\n // Check if value is actually changing\\n if (flashLoanPaused == paused) {\\n return; // No change needed\\n }\\n\\n emit FlashLoanPauseChanged(flashLoanPaused, paused);\\n flashLoanPaused = paused;\\n }\\n\\n /**\\n * @notice Updates the label for a specific pool (excluding the Core Pool)\\n * @param poolId ID of the pool to update\\n * @param newLabel The new label for the pool\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist\\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string\\n * @custom:event PoolLabelUpdated Emitted after the pool label is updated\\n */\\n function setPoolLabel(uint96 poolId, string calldata newLabel) external {\\n ensureAllowed(\\\"setPoolLabel(uint96,string)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n if (bytes(newLabel).length == 0) revert EmptyPoolLabel();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (keccak256(bytes(pool.label)) == keccak256(bytes(newLabel))) {\\n return;\\n }\\n\\n emit PoolLabelUpdated(poolId, pool.label, newLabel);\\n pool.label = newLabel;\\n }\\n\\n /**\\n * @notice updates active status for a specific pool (excluding the Core Pool)\\n * @param poolId id of the pool to update\\n * @param active true to enable, false to disable\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:event PoolActiveStatusUpdated Emitted after the pool active status is updated.\\n */\\n function setPoolActive(uint96 poolId, bool active) external {\\n ensureAllowed(\\\"setPoolActive(uint96,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (pool.isActive == active) {\\n return;\\n }\\n\\n emit PoolActiveStatusUpdated(poolId, pool.isActive, active);\\n pool.isActive = active;\\n }\\n\\n /**\\n * @notice Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\\n * @param poolId ID of the pool to update.\\n * @param allowFallback True to allow fallback to Core Pool, false to disable.\\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\\n * @custom:event PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\\n */\\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external {\\n ensureAllowed(\\\"setAllowCorePoolFallback(uint96,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\\n\\n PoolData storage pool = pools[poolId];\\n\\n if (pool.allowCorePoolFallback == allowFallback) {\\n return;\\n }\\n\\n emit PoolFallbackStatusUpdated(poolId, pool.allowCorePoolFallback, allowFallback);\\n pool.allowCorePoolFallback = allowFallback;\\n }\\n\\n /**\\n * @notice Updates the `isBorrowAllowed` flag for a market in a pool.\\n * @param poolId The ID of the pool.\\n * @param vToken The address of the market (vToken).\\n * @param borrowAllowed The new borrow allowed status.\\n * @custom:error PoolDoesNotExist Reverts if the pool ID is invalid.\\n * @custom:error MarketConfigNotFound Reverts if the market is not listed in the pool.\\n * @custom:event BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\\n */\\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external {\\n ensureAllowed(\\\"setIsBorrowAllowed(uint96,address,bool)\\\");\\n\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\\n Market storage m = _poolMarkets[index];\\n\\n if (!m.isListed) {\\n revert MarketConfigNotFound();\\n }\\n\\n if (m.isBorrowAllowed == borrowAllowed) {\\n return;\\n }\\n\\n emit BorrowAllowedUpdated(poolId, vToken, m.isBorrowAllowed, borrowAllowed);\\n m.isBorrowAllowed = borrowAllowed;\\n }\\n\\n /**\\n * @notice Sets the DeviationBoundedOracle for conservative CF-path pricing\\n * @param newDeviationBoundedOracle The new DeviationBoundedOracle contract\\n * @return uint256 0=success, otherwise a failure\\n */\\n function setDeviationBoundedOracle(\\n IDeviationBoundedOracle newDeviationBoundedOracle\\n ) external compareAddress(address(deviationBoundedOracle), address(newDeviationBoundedOracle)) returns (uint256) {\\n ensureAllowed(\\\"setDeviationBoundedOracle(address)\\\");\\n\\n ensureNonzeroAddress(address(newDeviationBoundedOracle));\\n\\n IDeviationBoundedOracle oldDeviationBoundedOracle = deviationBoundedOracle;\\n deviationBoundedOracle = newDeviationBoundedOracle;\\n\\n emit NewDeviationBoundedOracle(oldDeviationBoundedOracle, newDeviationBoundedOracle);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle\\n * @param newOracle The new price oracle to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setPriceOracle(\\n ResilientOracleInterface newOracle\\n ) internal compareAddress(address(oracle), address(newOracle)) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n ensureNonzeroAddress(address(newOracle));\\n\\n // Track the old oracle for the comptroller\\n ResilientOracleInterface oldOracle = oracle;\\n\\n // Set comptroller's oracle to newOracle\\n oracle = newOracle;\\n\\n // Emit NewPriceOracle(oldOracle, newOracle)\\n emit NewPriceOracle(oldOracle, newOracle);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the close factor. Used by _setCloseFactor and setCloseFactor\\n * @param newCloseFactorMantissa The new close factor to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setCloseFactor(\\n uint256 newCloseFactorMantissa\\n ) internal compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\\n // Check caller is admin\\n ensureAdmin();\\n\\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\\n\\n //-- Check close factor <= 0.9\\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\\n //-- Check close factor >= 0.05\\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\\n\\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\\n }\\n\\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\\n closeFactorMantissa = newCloseFactorMantissa;\\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the collateral factor and the liquidation threshold. Used by setCollateralFactor\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the factor on\\n * @param newCollateralFactorMantissa The new collateral factor to be set\\n * @param newLiquidationThresholdMantissa The new liquidation threshold to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) internal returns (uint256) {\\n ensureNonzeroAddress(address(vToken));\\n\\n // Check if pool exists\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n // Verify market is listed in the pool\\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, address(vToken))];\\n ensureListed(market);\\n\\n //-- Check collateral factor <= 1\\n if (newCollateralFactorMantissa > mantissaOne) {\\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\\n }\\n\\n // If collateral factor != 0, fail if price == 0\\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\\n }\\n\\n // Ensure that liquidation threshold <= 1\\n if (newLiquidationThresholdMantissa > mantissaOne) {\\n return fail(Error.INVALID_LIQUIDATION_THRESHOLD, FailureInfo.SET_LIQUIDATION_THRESHOLD_VALIDATION);\\n }\\n\\n // Ensure that liquidation threshold >= CF\\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\\n return\\n fail(\\n Error.INVALID_LIQUIDATION_THRESHOLD,\\n FailureInfo.COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n );\\n }\\n\\n // Set market's collateral factor to new collateral factor, remember old value\\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\\n market.collateralFactorMantissa = newCollateralFactorMantissa;\\n\\n // Emit event with poolId, asset, old collateral factor, and new collateral factor\\n emit NewCollateralFactor(poolId, vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\\n }\\n\\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\\n\\n emit NewLiquidationThreshold(\\n poolId,\\n vToken,\\n oldLiquidationThresholdMantissa,\\n newLiquidationThresholdMantissa\\n );\\n }\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the liquidation incentive. Used by setLiquidationIncentive\\n * @param poolId The ID of the pool.\\n * @param vToken The market to set the Incentive for\\n * @param newLiquidationIncentiveMantissa The new liquidation incentive to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n )\\n internal\\n compareValue(\\n _poolMarkets[getPoolMarketIndex(poolId, vToken)].liquidationIncentiveMantissa,\\n newLiquidationIncentiveMantissa\\n )\\n returns (uint256)\\n {\\n // Check if pool exists\\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\\n\\n // Verify market is listed in the pool\\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, vToken)];\\n ensureListed(market);\\n\\n require(newLiquidationIncentiveMantissa >= mantissaOne, \\\"incentive < 1e18\\\");\\n\\n emit NewLiquidationIncentive(\\n poolId,\\n vToken,\\n market.liquidationIncentiveMantissa,\\n newLiquidationIncentiveMantissa\\n );\\n\\n // Set liquidation incentive to new incentive\\n market.liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the borrow caps. Used by _setMarketBorrowCaps and setMarketBorrowCaps\\n * @param vTokens The markets to set the borrow caps on\\n * @param newBorrowCaps The new borrow caps to be set\\n */\\n function __setMarketBorrowCaps(VToken[] memory vTokens, uint256[] memory newBorrowCaps) internal {\\n ensureAllowed(\\\"_setMarketBorrowCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numBorrowCaps = newBorrowCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\\n }\\n }\\n\\n /**\\n * @dev Updates the supply caps. Used by _setMarketSupplyCaps and setMarketSupplyCaps\\n * @param vTokens The markets to set the supply caps on\\n * @param newSupplyCaps The new supply caps to be set\\n */\\n function __setMarketSupplyCaps(VToken[] memory vTokens, uint256[] memory newSupplyCaps) internal {\\n ensureAllowed(\\\"_setMarketSupplyCaps(address[],uint256[])\\\");\\n\\n uint256 numMarkets = vTokens.length;\\n uint256 numSupplyCaps = newSupplyCaps.length;\\n\\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \\\"invalid input\\\");\\n\\n for (uint256 i; i < numMarkets; ++i) {\\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\\n }\\n }\\n\\n /**\\n * @dev Updates the prime token. Used by _setPrimeToken and setPrimeToken\\n * @param _prime The new prime token to be set\\n * @return uint256 0=success, otherwise reverted\\n */\\n function __setPrimeToken(IPrime _prime) internal returns (uint) {\\n ensureAdmin();\\n ensureNonzeroAddress(address(_prime));\\n\\n IPrime oldPrime = prime;\\n prime = _prime;\\n emit NewPrimeToken(oldPrime, _prime);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Updates the forced liquidation. Used by _setForcedLiquidation and setForcedLiquidation\\n * @param vTokenBorrowed The market to set the forced liquidation on\\n * @param enable Whether to enable forced liquidations\\n */\\n function __setForcedLiquidation(address vTokenBorrowed, bool enable) internal {\\n ensureAllowed(\\\"_setForcedLiquidation(address,bool)\\\");\\n if (vTokenBorrowed != address(vaiController)) {\\n ensureListed(getCorePoolMarket(vTokenBorrowed));\\n }\\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\\n }\\n\\n /**\\n * @dev Updates the actions paused. Used by _setActionsPaused and setActionsPaused\\n * @param markets_ The markets to set the actions paused on\\n * @param actions_ The actions to set the paused state on\\n * @param paused_ The new paused state to be set\\n */\\n function __setActionsPaused(address[] memory markets_, Action[] memory actions_, bool paused_) internal {\\n ensureAllowed(\\\"_setActionsPaused(address[],uint8[],bool)\\\");\\n\\n uint256 numMarkets = markets_.length;\\n uint256 numActions = actions_.length;\\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x97c8edf14a752732fbf1e8cc4fc4aeca6dd83d56a048d9ed4a17ac06135d613a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { VToken } from \\\"../../../Tokens/VTokens/VToken.sol\\\";\\nimport { Action } from \\\"../../ComptrollerInterface.sol\\\";\\nimport { VAIControllerInterface } from \\\"../../../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"../../../Comptroller/ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../../../Tokens/Prime/IPrime.sol\\\";\\n\\ninterface ISetterFacet {\\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\\n\\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\\n\\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\\n\\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\\n\\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\\n\\n function setCollateralFactor(\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256);\\n\\n function setCollateralFactor(\\n uint96 poolId,\\n VToken vToken,\\n uint256 newCollateralFactorMantissa,\\n uint256 newLiquidationThresholdMantissa\\n ) external returns (uint256);\\n\\n function setLiquidationIncentive(\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256);\\n\\n function setLiquidationIncentive(\\n uint96 poolId,\\n address vToken,\\n uint256 newLiquidationIncentiveMantissa\\n ) external returns (uint256);\\n\\n function _setLiquidatorContract(address newLiquidatorContract_) external;\\n\\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\\n\\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\\n\\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\\n\\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\\n\\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\\n\\n function _setProtocolPaused(bool state) external returns (bool);\\n\\n function setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\\n\\n function _setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\\n\\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\\n\\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\\n\\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\\n\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256);\\n\\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external returns (uint256);\\n\\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\\n\\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\\n\\n function _setForcedLiquidation(address vToken, bool enable) external;\\n\\n function setPrimeToken(IPrime _prime) external returns (uint256);\\n\\n function _setPrimeToken(IPrime _prime) external returns (uint);\\n\\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external;\\n\\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external;\\n\\n function _setXVSToken(address xvs_) external;\\n\\n function _setXVSVToken(address xvsVToken_) external;\\n\\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external;\\n\\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external;\\n\\n function setPoolActive(uint96 poolId, bool active) external;\\n\\n function setPoolLabel(uint96 poolId, string calldata newLabel) external;\\n\\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external;\\n\\n function setFlashLoanPaused(bool paused) external;\\n\\n function setDeviationBoundedOracle(IDeviationBoundedOracle newDeviationBoundedOracle) external returns (uint256);\\n}\\n\",\"keccak256\":\"0xd29980800653e500a3a995cbc30cd00c6074c5204c86426bd28d4e23e18dba8a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b50613d878061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106104d2575f3560e01c80638a7dc16511610284578063bf32442d11610161578063dce15449116100d5578063f445d7031161008f578063f445d70314610bd6578063f519fc3014610c03578063f851a44014610c16578063fa6331d814610c28578063fd51a3ad14610c31578063fe40768f14610c44575f80fd5b8063dce1544914610b3b578063dcfbc0c714610b4e578063e0f6123d14610b61578063e37d4b7914610b83578063e85a296014610bba578063e875544614610bcd575f80fd5b8063d136af4411610126578063d136af4414610740578063d24febad14610ae3578063d3270f9914610af6578063d463654c14610b09578063d6ad5c3914610b10578063d7c46d2d14610b23575f80fd5b8063bf32442d14610a7e578063c32094c7146108ff578063c5b4db5514610a8f578063c5f956af14610abd578063c7ee005e14610ad0575f80fd5b80639bf34cbb116101f8578063b8324c7c116101bd578063b8324c7c146109c2578063b88d846b14610a1d578063bb82aa5e14610a30578063bb85745014610a43578063bbb8864a14610a56578063bec04f7214610a75575f80fd5b80639bf34cbb146109635780639cfdd9e614610976578063a657e57914610989578063a89766dd1461099c578063b2eafc39146109af575f80fd5b80639254f5e5116102495780639254f5e5146108ec5780639460c8b5146108ff57806394b2294b1461091257806396c990641461091b5780639bb27d621461093d5780639bd8f6e814610950575f80fd5b80638a7dc165146108855780638b3113f6146107535780638c1ac18a146108a45780639159b177146108c6578063919a3736146108d9575f80fd5b80634964f48c116103b25780635dd3fc9d1161032657806373769099116102eb57806373769099146107ed578063765513831461082d5780637938146f1461083f5780637d172bd5146108525780637dc0d1d0146108655780637fb8e8cd14610878575f80fd5b80635dd3fc9d1461079f5780635f5af1aa146107be578063607ef6c1146105a95780636662c7c9146107d1578063719f701b146107e4575f80fd5b806351a485e41161037757806351a485e414610740578063522c656b1461075357806352d84d1e14610766578063530e784f1461077957806355ee1fe1146107795780635cc4fdeb1461078c575f80fd5b80634964f48c146106d55780634a584432146106e85780634d99c776146107075780634e0853db1461071a5780634ef233fc1461072d575f80fd5b80632678224711610449578063317b0b771161040e578063317b0b771461058157806335439240146106655780634088c73e1461067857806341a18d2c14610685578063425fad58146106af57806342adb211146106c2575f80fd5b8063267822471461060d5780632a6a6065146106205780632b5d790c146105fa5780632bc7e29e146106335780632ec0412414610652575f80fd5b806312348e961161049a57806312348e961461058157806317db216314610594578063186db48f146105a957806321af4569146105bc57806324a3d622146105e757806324aaa220146105fa575f80fd5b806302c3bcbb146104d657806304ef9d581461050857806308e0225c146105115780630db4b4e51461053b57806310b9833814610544575b5f80fd5b6104f56104e4366004613244565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6104f560225481565b6104f561051f36600461325f565b601360209081525f928352604080842090915290825290205481565b6104f5601d5481565b61057161055236600461325f565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016104ff565b6104f561058f366004613296565b610c57565b6105a76105a23660046132ba565b610c67565b005b6105a76105b736600461334a565b610d1b565b601e546105cf906001600160a01b031681565b6040516001600160a01b0390911681526020016104ff565b600a546105cf906001600160a01b031681565b6105a76106083660046133b1565b610d8c565b6001546105cf906001600160a01b031681565b61057161062e36600461342f565b610e00565b6104f5610641366004613244565b60166020525f908152604090205481565b6104f5610660366004613296565b610e96565b6104f5610673366004613465565b610f19565b6018546105719060ff1681565b6104f561069336600461325f565b601260209081525f928352604080842090915290825290205481565b6018546105719062010000900460ff1681565b6105a76106d03660046134a1565b610f50565b6105a76106e33660046134cd565b610ff8565b6104f56106f6366004613244565b601f6020525f908152604090205481565b6104f56107153660046134e7565b61112d565b6105a7610728366004613501565b61114a565b6105a761073b366004613244565b61120d565b6105a761074e36600461334a565b61133b565b6105a76107613660046134a1565b6113a6565b6105cf610774366004613296565b6113b4565b6104f5610787366004613244565b6113dc565b6104f561079a366004613501565b6113e6565b6104f56107ad366004613244565b602b6020525f908152604090205481565b6104f56107cc366004613244565b611414565b6105a76107df366004613296565b6114ab565b6104f5601c5481565b6108156107fb366004613244565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016104ff565b60185461057190610100900460ff1681565b6105a761084d3660046134cd565b611537565b601b546105cf906001600160a01b031681565b6004546105cf906001600160a01b031681565b6039546105719060ff1681565b6104f5610893366004613244565b60146020525f908152604090205481565b6105716108b2366004613244565b602d6020525f908152604090205460ff1681565b6104f56108d4366004613533565b61165e565b6105a76108e7366004613244565b611697565b6015546105cf906001600160a01b031681565b6104f561090d366004613244565b611703565b6104f560075481565b61092e610929366004613574565b61170d565b6040516104ff939291906135bb565b6025546105cf906001600160a01b031681565b6104f561095e3660046135e4565b6117ba565b6104f5610971366004613244565b6117e7565b6104f5610984366004613244565b61187d565b603754610815906001600160601b031681565b6105a76109aa36600461360e565b611914565b6020546105cf906001600160a01b031681565b6109f96109d0366004613244565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104ff565b6105a7610a2b366004613629565b611a55565b6002546105cf906001600160a01b031681565b6105a7610a51366004613244565b611bb9565b6104f5610a64366004613244565b602a6020525f908152604090205481565b6104f560175481565b6033546001600160a01b03166105cf565b610aa56ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b0390911681526020016104ff565b6021546105cf906001600160a01b031681565b6031546105cf906001600160a01b031681565b6104f5610af13660046136a5565b611c4e565b6026546105cf906001600160a01b031681565b6108155f81565b6105a7610b1e36600461342f565b611db5565b6039546105cf9061010090046001600160a01b031681565b6105cf610b493660046135e4565b611e5e565b6003546105cf906001600160a01b031681565b610571610b6f366004613244565b60386020525f908152604090205460ff1681565b6109f9610b91366004613244565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b610571610bc83660046136c2565b611e92565b6104f560055481565b610571610be436600461325f565b603260209081525f928352604080842090915290825290205460ff1681565b6104f5610c11366004613244565b611ed6565b5f546105cf906001600160a01b031681565b6104f5601a5481565b6104f5610c3f3660046135e4565b611f6d565b6104f5610c52366004613244565b612011565b5f610c61826120d0565b92915050565b610c88604051806060016040528060328152602001613b34603291396121aa565b6015546001600160a01b03838116911614610cae57610cae610ca98361225a565b61227c565b6001600160a01b038381165f81815260326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fc080966e9e93529edc1b244180c245bc60f3d86f1e690a17651a5e428746a8cd91015b60405180910390a3505050565b610d868484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f920191909152506122c192505050565b50505050565b610df98585808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284375f92019190915250869250612411915050565b5050505050565b5f610e3f6040518060400160405280601881526020017f5f73657450726f746f636f6c50617573656428626f6f6c2900000000000000008152506121aa565b60188054831515620100000262ff0000199091161790556040517fd7500633dd3ddd74daa7af62f8c8404c7fe4a81da179998db851696bed004b3890610e8a90841515815260200190565b60405180910390a15090565b5f60175482808203610ec35760405162461bcd60e51b8152600401610eba906136f1565b60405180910390fd5b610ecb6124a0565b601780549085905560408051828152602081018790527f73747d68b346dce1e932bcd238282e7ac84c01569e1f8d0469c222fdc6e9d5a491015b60405180910390a15f9350505b5050919050565b5f610f3b6040518060600160405280602f8152602001613b8f602f91396121aa565b610f468484846124ec565b90505b9392505050565b610f716040518060600160405280602a8152602001613bbe602a91396121aa565b610f7a8261263e565b6001600160a01b0382165f9081526038602052604090205481151560ff909116151503610fa5575050565b6001600160a01b0382165f81815260386020526040808220805460ff191685151590811790915590519092917f1f4df5032f431b9890646a781be28b0d693e581666d1a80be27ae3959069172291a35050565b6110366040518060400160405280601a81526020017f736574506f6f6c4163746976652875696e7439362c626f6f6c290000000000008152506121aa565b6037546001600160601b03908116908316111561107157604051632db8671b60e11b81526001600160601b0383166004820152602401610eba565b6001600160601b03821661109857604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151560ff9091161515036110c857505050565b60028101546040805160ff9092161515825283151560208301526001600160601b038516917f75e42fceb039532886a9d75717e843bfef67fd7f6f91f0fc5b1d48e9ce8a1ba9910160405180910390a2600201805460ff191691151591909117905550565b6001600160a01b031660a09190911b6001600160a01b0319161790565b601b546001600160a01b039081169084908116820361117b5760405162461bcd60e51b8152600401610eba9061373c565b6111836124a0565b61118c8561263e565b601b546001600160a01b0316156111a5576111a561268c565b601b80546001600160a01b0319166001600160a01b038716908117909155601c859055601d84905560408051868152602081018690527f7059037d74ee16b0fb06a4a30f3348dd2635f301f92e373c92899a25a522ef6e910160405180910390a25050505050565b6112156124a0565b61121e8161263e565b5f816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061127f919061377e565b6033549091506001600160a01b038083169116146112df5760405162461bcd60e51b815260206004820152601a60248201527f696e76616c6964207876732076746f6b656e20616464726573730000000000006044820152606401610eba565b6034546040516001600160a01b038085169216907f2565e1579c0926afb7113edbfd85373e85cadaa3e0346f04de19686a2bb86ed1905f90a350603480546001600160a01b0319166001600160a01b0392909216919091179055565b610d868484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f9201919091525061281b92505050565b6113b0828261296b565b5050565b600d81815481106113c3575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610c6182612a0b565b5f6114086040518060600160405280602c8152602001613c34602c91396121aa565b610f465f858585612aa2565b600a545f906001600160a01b03908116908390811682036114475760405162461bcd60e51b8152600401610eba9061373c565b61144f6124a0565b6114588461263e565b600a80546001600160a01b038681166001600160a01b03198316179092556040519116907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90610f059083908890613799565b601a54818082036114ce5760405162461bcd60e51b8152600401610eba906136f1565b6114d66124a0565b601b546001600160a01b0316156114ef576114ef61268c565b601a80549084905560408051828152602081018690527fe81d4ac15e5afa1e708e66664eddc697177423d950d133bda8262d8885e6da3b91015b60405180910390a150505050565b611558604051806060016040528060258152602001613c89602591396121aa565b6037546001600160601b03908116908316111561159357604051632db8671b60e11b81526001600160601b0383166004820152602401610eba565b6001600160601b0382166115ba57604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151561010090910460ff161515036115ee57505050565b60028101546040805161010090920460ff161515825283151560208301526001600160601b038516917f9d2a9183b06e3492f91d3d88ae222e700c8873dd0068f9c3fc783eccb96a1ec4910160405180910390a260020180549115156101000261ff001990921691909117905550565b5f611680604051806060016040528060338152602001613cae603391396121aa565b61168c85858585612aa2565b90505b949350505050565b61169f6124a0565b6116a88161263e565b6033546040516001600160a01b038084169216907ffe7fd0d872def0f65050e9f38fc6691d0c192c694a56f09b04bec5fb2ea61f2b905f90a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5f610c6182612cbf565b60366020525f9081526040902080548190611727906137b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611753906137b3565b801561179e5780601f106117755761010080835404028352916020019161179e565b820191905f5260205f20905b81548152906001019060200180831161178157829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6117dc604051806060016040528060288152602001613ce1602891396121aa565b610f495f84846124ec565b6026545f906001600160a01b039081169083908116820361181a5760405162461bcd60e51b8152600401610eba9061373c565b6118226124a0565b61182b8461263e565b602680546001600160a01b038681166001600160a01b0319831681179093556040519116917f0f7eb572d1b3053a0a3a33c04151364cf88d163182a5e4e1088cb8e52321e08a91610f05918491613799565b6015545f906001600160a01b03908116908390811682036118b05760405162461bcd60e51b8152600401610eba9061373c565b6118b86124a0565b6118c18461263e565b601580546001600160a01b038681166001600160a01b03198316179092556040519116907fe1ddcb2dab8e5b03cfc8c67a0d5861d91d16f7bd2612fd381faf4541d212c9b290610f059083908890613799565b611935604051806060016040528060278152602001613d09602791396121aa565b6037546001600160601b03908116908416111561197057604051632db8671b60e11b81526001600160601b0384166004820152602401610eba565b5f61197b848461112d565b5f81815260096020526040902080549192509060ff166119ae57604051630665210960e21b815260040160405180910390fd5b82151581600601600c9054906101000a900460ff161515036119d1575050505050565b600681015460408051600160601b90920460ff161515825284151560208301526001600160a01b038616916001600160601b038816917fe40f9c4af130bdb5bd1650ab4bc918dba9d900fa94685f0113e72a6cfe6c5fcc910160405180910390a36006018054921515600160601b0260ff60601b1990931692909217909155505050565b611a936040518060400160405280601b81526020017f736574506f6f6c4c6162656c2875696e7439362c737472696e672900000000008152506121aa565b6037546001600160601b039081169084161115611ace57604051632db8671b60e11b81526001600160601b0384166004820152602401610eba565b6001600160601b038316611af557604051630203217b60e61b815260040160405180910390fd5b5f819003611b165760405163522e397360e11b815260040160405180910390fd5b6001600160601b0383165f90815260366020526040908190209051611b3e90849084906137eb565b60405190819003812090611b539083906137fa565b604051809103902003611b665750505050565b836001600160601b03167f1ebc260ee8077871ff0b70b184ff9dac4ecee8b0f7dcc4f3a3f5068549f5078e825f018585604051611ba593929190613894565b60405180910390a280610df983858361398b565b6025546001600160a01b0390811690829081168203611bea5760405162461bcd60e51b8152600401610eba9061373c565b611bf26124a0565b611bfb8361263e565b602580546001600160a01b038581166001600160a01b03198316179092556040519116907fa5ea5616d5f6dbbaa62fdfcf3856723216eed485c394d9e51ec8e6d40e1d1ac1906115299083908790613799565b6020545f90611c65906001600160a01b0316612d34565b670de0b6b3a76400008210611cae5760405162461bcd60e51b815260206004820152600f60248201526e70657263656e74203e3d203130302560881b6044820152606401610eba565b611cb78461263e565b611cc08361263e565b6020805460218054602280546001600160a01b03198086166001600160a01b038c8116919091179097558316898716179093558690556040519284169316917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e890611d2e9085908a90613799565b60405180910390a17f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac8287604051611d67929190613799565b60405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a15f5b979650505050505050565b611df36040518060400160405280601881526020017f736574466c6173684c6f616e50617573656428626f6f6c2900000000000000008152506121aa565b60395481151560ff909116151503611e085750565b6039546040805160ff9092161515825282151560208301527f79bcfb2700d56371c7684799f99d64cbcd91f1e360f8048a42c9ba534be7c0a8910160405180910390a16039805460ff1916911515919091179055565b6008602052815f5260405f208181548110611e77575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611ebc57611ebc613728565b815260208101919091526040015f205460ff169392505050565b6028545f906001600160a01b0390811690839081168203611f095760405162461bcd60e51b8152600401610eba9061373c565b611f116124a0565b611f1a8461263e565b602880546001600160a01b038681166001600160a01b03198316179092556040519116907f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd490610f059083908890613799565b5f611f76612d8f565b60185460ff16158015611f915750601854610100900460ff16155b611fcd5760405162461bcd60e51b815260206004820152600d60248201526c159052481a5cc81c185d5cd959609a1b6044820152606401610eba565b6015546001600160a01b03163314611ff257611feb600e6016612ddd565b9050610c61565b6001600160a01b0383165f908152601660205260408120839055610f49565b6039545f906001600160a01b036101009091048116908390811682036120495760405162461bcd60e51b8152600401610eba9061373c565b61206a604051806060016040528060228152602001613d30602291396121aa565b6120738461263e565b603980546001600160a01b03868116610100908102610100600160a81b03198416179093556040519290910416907fc4877d82ec0586c93fbd01eb65785e064f0c31b594e7f413e5f16502f25cf27390610f059083908890613799565b5f600554828082036120f45760405162461bcd60e51b8152600401610eba906136f1565b6120fc6124a0565b604080516020808201835286825282518082018452670c7d713b49da00008152835191820190935266b1a2bc2ec500008152815183519293921080612142575082518151115b1561215c57612152600580612ddd565b9550505050610f12565b600580549088905560408051828152602081018a90527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9910160405180910390a15f98975050505050505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906121dc9033908590600401613a45565b602060405180830381865afa1580156121f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061221b9190613a68565b6122575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610eba565b50565b5f60095f6122685f8561112d565b81526020019081526020015f209050919050565b805460ff166122575760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610eba565b6122e2604051806060016040528060298152602001613c60602991396121aa565b8151815181158015906122f457508082145b6123305760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610eba565b5f5b82811015610df95783818151811061234c5761234c613a83565b6020026020010151601f5f87848151811061236957612369613a83565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20819055508481815181106123a6576123a6613a83565b60200260200101516001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68583815181106123ea576123ea613a83565b602002602001015160405161240191815260200190565b60405180910390a2600101612332565b612432604051806060016040528060298152602001613b66602991396121aa565b825182515f5b82811015612498575f5b8281101561248f5761248787838151811061245f5761245f613a83565b602002602001015187838151811061247957612479613a83565b602002602001015187612e54565b600101612442565b50600101612438565b505050505050565b5f546001600160a01b031633146124ea5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610eba565b565b5f60095f6124fa868661112d565b81526020019081526020015f20600501548280820361252b5760405162461bcd60e51b8152600401610eba906136f1565b6037546001600160601b03908116908716111561256657604051632db8671b60e11b81526001600160601b0387166004820152602401610eba565b5f60095f612574898961112d565b81526020019081526020015f20905061258c8161227c565b670de0b6b3a76400008510156125d75760405162461bcd60e51b815260206004820152601060248201526f0d2dcc6cadce8d2ecca40784062ca62760831b6044820152606401610eba565b856001600160a01b0316876001600160601b03167fc1d7bc090f3a87255c2f4e56f66d1b7a49683d279f77921b1701aa5d733ef745836005015488604051612629929190918252602082015260400190565b60405180910390a3600581018590555f611daa565b6001600160a01b0381166122575760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610eba565b601c54158061269c5750601c5443105b156126a357565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156126ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127119190613a97565b9050805f0361271e575050565b5f8061272c43601c54612ef8565b90505f61273b601a5483612f31565b905080841061274c57809250612750565b8392505b601d54831015612761575050505050565b43601c55601b5461277f906001600160a01b03878116911685612f72565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156127fe575f80fd5b505af1158015612810573d5f803e3d5ffd5b505050505050505050565b61283c604051806060016040528060298152602001613be8602991396121aa565b81518151811580159061284e57508082145b61288a5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610eba565b5f5b82811015610df9578381815181106128a6576128a6613a83565b602002602001015160275f8784815181106128c3576128c3613a83565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208190555084818151811061290057612900613a83565b60200260200101516001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f885838151811061294457612944613a83565b602002602001015160405161295b91815260200190565b60405180910390a260010161288c565b61298c604051806060016040528060238152602001613c11602391396121aa565b6015546001600160a01b038381169116146129ad576129ad610ca98361225a565b6001600160a01b0382165f818152602d6020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b6004545f906001600160a01b0390811690839081168203612a3e5760405162461bcd60e51b8152600401610eba9061373c565b612a466124a0565b612a4f8461263e565b600480546001600160a01b038681166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e2290610f059083908890613799565b5f612aac8461263e565b6037546001600160601b039081169086161115612ae757604051632db8671b60e11b81526001600160601b0386166004820152602401610eba565b5f60095f612af5888861112d565b81526020019081526020015f209050612b0d8161227c565b670de0b6b3a7640000841115612b3157612b2960066008612ddd565b91505061168f565b8315801590612bab57506004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa158015612b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ba99190613a97565b155b15612bbc57612b29600d6009612ddd565b670de0b6b3a7640000831115612bd857612b2960146019612ddd565b83831015612bec57612b296014601a612ddd565b6001810154848114612c4f576001820185905560408051828152602081018790526001600160a01b038816916001600160601b038a16917f0d1a615379dc62cec7bc63b7e313a07ed659918f4ad3720b3af8041b305146f2910160405180910390a35b6004820154848114612cb2576004830185905560408051828152602081018790526001600160a01b038916916001600160601b038b16917fc90f7b48c299a8d58b0b9e2756e27773c6fb1daab159af052d6c5b791bc7eef7910160405180910390a35b5f98975050505050505050565b5f612cc86124a0565b612cd18261263e565b603180546001600160a01b038481166001600160a01b03198316179092556040519116907fcb20dab7409e4fb972d9adccb39530520b226ce6940d85c9523a499b950b6ea390612d249083908690613799565b60405180910390a15f9392505050565b5f546001600160a01b031633148061221b5750336001600160a01b038216146122575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610eba565b60185462010000900460ff16156124ea5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610eba565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836014811115612e1157612e11613728565b83601a811115612e2357612e23613728565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610f4957610f49613728565b612e60610ca98461225a565b6001600160a01b0383165f9081526029602052604081208291846008811115612e8b57612e8b613728565b815260208101919091526040015f20805460ff1916911515919091179055816008811115612ebb57612ebb613728565b836001600160a01b03167f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d83604051610d0e911515815260200190565b5f610f498383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612fc9565b5f610f4983836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612ff7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612fc4908490613050565b505050565b5f8184841115612fec5760405162461bcd60e51b8152600401610eba9190613aae565b50610f468385613ad4565b5f831580613003575082155b1561300f57505f610f49565b5f61301a8486613ae7565b9050836130278683613afe565b1483906130475760405162461bcd60e51b8152600401610eba9190613aae565b50949350505050565b5f6130a4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166131239092919063ffffffff16565b905080515f14806130c45750808060200190518101906130c49190613a68565b612fc45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610eba565b6060610f4684845f85855f80866001600160a01b031685876040516131489190613b1d565b5f6040518083038185875af1925050503d805f8114613182576040519150601f19603f3d011682016040523d82523d5f602084013e613187565b606091505b5091509150611daa87838387606083156132015782515f036131fa576001600160a01b0385163b6131fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610eba565b508161168f565b61168f83838151156132165781518083602001fd5b8060405162461bcd60e51b8152600401610eba9190613aae565b6001600160a01b0381168114612257575f80fd5b5f60208284031215613254575f80fd5b8135610f4981613230565b5f8060408385031215613270575f80fd5b823561327b81613230565b9150602083013561328b81613230565b809150509250929050565b5f602082840312156132a6575f80fd5b5035919050565b8015158114612257575f80fd5b5f805f606084860312156132cc575f80fd5b83356132d781613230565b925060208401356132e781613230565b915060408401356132f7816132ad565b809150509250925092565b5f8083601f840112613312575f80fd5b50813567ffffffffffffffff811115613329575f80fd5b6020830191508360208260051b8501011115613343575f80fd5b9250929050565b5f805f806040858703121561335d575f80fd5b843567ffffffffffffffff80821115613374575f80fd5b61338088838901613302565b90965094506020870135915080821115613398575f80fd5b506133a587828801613302565b95989497509550505050565b5f805f805f606086880312156133c5575f80fd5b853567ffffffffffffffff808211156133dc575f80fd5b6133e889838a01613302565b90975095506020880135915080821115613400575f80fd5b5061340d88828901613302565b9094509250506040860135613421816132ad565b809150509295509295909350565b5f6020828403121561343f575f80fd5b8135610f49816132ad565b80356001600160601b0381168114613460575f80fd5b919050565b5f805f60608486031215613477575f80fd5b6134808461344a565b9250602084013561349081613230565b929592945050506040919091013590565b5f80604083850312156134b2575f80fd5b82356134bd81613230565b9150602083013561328b816132ad565b5f80604083850312156134de575f80fd5b6134bd8361344a565b5f80604083850312156134f8575f80fd5b61327b8361344a565b5f805f60608486031215613513575f80fd5b833561351e81613230565b95602085013595506040909401359392505050565b5f805f8060808587031215613546575f80fd5b61354f8561344a565b9350602085013561355f81613230565b93969395505050506040820135916060013590565b5f60208284031215613584575f80fd5b610f498261344a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6135cd606083018661358d565b931515602083015250901515604090910152919050565b5f80604083850312156135f5575f80fd5b823561360081613230565b946020939093013593505050565b5f805f60608486031215613620575f80fd5b6132d78461344a565b5f805f6040848603121561363b575f80fd5b6136448461344a565b9250602084013567ffffffffffffffff80821115613660575f80fd5b818601915086601f830112613673575f80fd5b813581811115613681575f80fd5b876020828501011115613692575f80fd5b6020830194508093505050509250925092565b5f805f606084860312156136b7575f80fd5b833561348081613230565b5f80604083850312156136d3575f80fd5b82356136de81613230565b915060208301356009811061328b575f80fd5b6020808252601e908201527f6f6c642076616c75652069732073616d65206173206e65772076616c75650000604082015260600190565b634e487b7160e01b5f52602160045260245ffd5b60208082526022908201527f6f6c6420616464726573732069732073616d65206173206e6577206164647265604082015261737360f01b606082015260800190565b5f6020828403121561378e575f80fd5b8151610f4981613230565b6001600160a01b0392831681529116602082015260400190565b600181811c908216806137c757607f821691505b6020821081036137e557634e487b7160e01b5f52602260045260245ffd5b50919050565b818382375f9101908152919050565b5f808354613807816137b3565b6001828116801561381f576001811461383457613860565b60ff1984168752821515830287019450613860565b875f526020805f205f5b858110156138575781548a82015290840190820161383e565b50505082870194505b50929695505050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f8085546138a5816137b3565b806040860152606060018084165f81146138c657600181146138e257613911565b60ff1985166060890152606084151560051b8901019550613911565b8a5f526020805f205f5b868110156139075781548b82018701529084019082016138ec565b8a01606001975050505b5050505050828103602084015261392981858761386c565b9695505050505050565b634e487b7160e01b5f52604160045260245ffd5b601f821115612fc457805f5260205f20601f840160051c8101602085101561396c5750805b601f840160051c820191505b81811015610df9575f8155600101613978565b67ffffffffffffffff8311156139a3576139a3613933565b6139b7836139b183546137b3565b83613947565b5f601f8411600181146139e8575f85156139d15750838201355b5f19600387901b1c1916600186901b178355610df9565b5f83815260208120601f198716915b82811015613a1757868501358255602094850194600190920191016139f7565b5086821015613a33575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b03831681526040602082018190525f90610f469083018461358d565b5f60208284031215613a78575f80fd5b8151610f49816132ad565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215613aa7575f80fd5b5051919050565b602081525f610f49602083018461358d565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c6157610c61613ac0565b8082028115828204841417610c6157610c61613ac0565b5f82613b1857634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f92019182525091905056fe5f736574466f726365644c69717569646174696f6e466f725573657228616464726573732c616464726573732c626f6f6c295f736574416374696f6e7350617573656428616464726573735b5d2c75696e74385b5d2c626f6f6c297365744c69717569646174696f6e496e63656e746976652875696e7439362c616464726573732c75696e743235362973657457686974654c697374466c6173684c6f616e4163636f756e7428616464726573732c626f6f6c295f7365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d295f736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c29736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e74323536295f7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d29736574416c6c6f77436f7265506f6f6c46616c6c6261636b2875696e7439362c626f6f6c29736574436f6c6c61746572616c466163746f722875696e7439362c616464726573732c75696e743235362c75696e74323536297365744c69717569646174696f6e496e63656e7469766528616464726573732c75696e74323536297365744973426f72726f77416c6c6f7765642875696e7439362c616464726573732c626f6f6c29736574446576696174696f6e426f756e6465644f7261636c65286164647265737329a2646970667358221220565945c5e9c23268c820f53390cd21154914aeaa407c9ffe8251b3b5175293a464736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106104d2575f3560e01c80638a7dc16511610284578063bf32442d11610161578063dce15449116100d5578063f445d7031161008f578063f445d70314610bd6578063f519fc3014610c03578063f851a44014610c16578063fa6331d814610c28578063fd51a3ad14610c31578063fe40768f14610c44575f80fd5b8063dce1544914610b3b578063dcfbc0c714610b4e578063e0f6123d14610b61578063e37d4b7914610b83578063e85a296014610bba578063e875544614610bcd575f80fd5b8063d136af4411610126578063d136af4414610740578063d24febad14610ae3578063d3270f9914610af6578063d463654c14610b09578063d6ad5c3914610b10578063d7c46d2d14610b23575f80fd5b8063bf32442d14610a7e578063c32094c7146108ff578063c5b4db5514610a8f578063c5f956af14610abd578063c7ee005e14610ad0575f80fd5b80639bf34cbb116101f8578063b8324c7c116101bd578063b8324c7c146109c2578063b88d846b14610a1d578063bb82aa5e14610a30578063bb85745014610a43578063bbb8864a14610a56578063bec04f7214610a75575f80fd5b80639bf34cbb146109635780639cfdd9e614610976578063a657e57914610989578063a89766dd1461099c578063b2eafc39146109af575f80fd5b80639254f5e5116102495780639254f5e5146108ec5780639460c8b5146108ff57806394b2294b1461091257806396c990641461091b5780639bb27d621461093d5780639bd8f6e814610950575f80fd5b80638a7dc165146108855780638b3113f6146107535780638c1ac18a146108a45780639159b177146108c6578063919a3736146108d9575f80fd5b80634964f48c116103b25780635dd3fc9d1161032657806373769099116102eb57806373769099146107ed578063765513831461082d5780637938146f1461083f5780637d172bd5146108525780637dc0d1d0146108655780637fb8e8cd14610878575f80fd5b80635dd3fc9d1461079f5780635f5af1aa146107be578063607ef6c1146105a95780636662c7c9146107d1578063719f701b146107e4575f80fd5b806351a485e41161037757806351a485e414610740578063522c656b1461075357806352d84d1e14610766578063530e784f1461077957806355ee1fe1146107795780635cc4fdeb1461078c575f80fd5b80634964f48c146106d55780634a584432146106e85780634d99c776146107075780634e0853db1461071a5780634ef233fc1461072d575f80fd5b80632678224711610449578063317b0b771161040e578063317b0b771461058157806335439240146106655780634088c73e1461067857806341a18d2c14610685578063425fad58146106af57806342adb211146106c2575f80fd5b8063267822471461060d5780632a6a6065146106205780632b5d790c146105fa5780632bc7e29e146106335780632ec0412414610652575f80fd5b806312348e961161049a57806312348e961461058157806317db216314610594578063186db48f146105a957806321af4569146105bc57806324a3d622146105e757806324aaa220146105fa575f80fd5b806302c3bcbb146104d657806304ef9d581461050857806308e0225c146105115780630db4b4e51461053b57806310b9833814610544575b5f80fd5b6104f56104e4366004613244565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6104f560225481565b6104f561051f36600461325f565b601360209081525f928352604080842090915290825290205481565b6104f5601d5481565b61057161055236600461325f565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016104ff565b6104f561058f366004613296565b610c57565b6105a76105a23660046132ba565b610c67565b005b6105a76105b736600461334a565b610d1b565b601e546105cf906001600160a01b031681565b6040516001600160a01b0390911681526020016104ff565b600a546105cf906001600160a01b031681565b6105a76106083660046133b1565b610d8c565b6001546105cf906001600160a01b031681565b61057161062e36600461342f565b610e00565b6104f5610641366004613244565b60166020525f908152604090205481565b6104f5610660366004613296565b610e96565b6104f5610673366004613465565b610f19565b6018546105719060ff1681565b6104f561069336600461325f565b601260209081525f928352604080842090915290825290205481565b6018546105719062010000900460ff1681565b6105a76106d03660046134a1565b610f50565b6105a76106e33660046134cd565b610ff8565b6104f56106f6366004613244565b601f6020525f908152604090205481565b6104f56107153660046134e7565b61112d565b6105a7610728366004613501565b61114a565b6105a761073b366004613244565b61120d565b6105a761074e36600461334a565b61133b565b6105a76107613660046134a1565b6113a6565b6105cf610774366004613296565b6113b4565b6104f5610787366004613244565b6113dc565b6104f561079a366004613501565b6113e6565b6104f56107ad366004613244565b602b6020525f908152604090205481565b6104f56107cc366004613244565b611414565b6105a76107df366004613296565b6114ab565b6104f5601c5481565b6108156107fb366004613244565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016104ff565b60185461057190610100900460ff1681565b6105a761084d3660046134cd565b611537565b601b546105cf906001600160a01b031681565b6004546105cf906001600160a01b031681565b6039546105719060ff1681565b6104f5610893366004613244565b60146020525f908152604090205481565b6105716108b2366004613244565b602d6020525f908152604090205460ff1681565b6104f56108d4366004613533565b61165e565b6105a76108e7366004613244565b611697565b6015546105cf906001600160a01b031681565b6104f561090d366004613244565b611703565b6104f560075481565b61092e610929366004613574565b61170d565b6040516104ff939291906135bb565b6025546105cf906001600160a01b031681565b6104f561095e3660046135e4565b6117ba565b6104f5610971366004613244565b6117e7565b6104f5610984366004613244565b61187d565b603754610815906001600160601b031681565b6105a76109aa36600461360e565b611914565b6020546105cf906001600160a01b031681565b6109f96109d0366004613244565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016104ff565b6105a7610a2b366004613629565b611a55565b6002546105cf906001600160a01b031681565b6105a7610a51366004613244565b611bb9565b6104f5610a64366004613244565b602a6020525f908152604090205481565b6104f560175481565b6033546001600160a01b03166105cf565b610aa56ec097ce7bc90715b34b9f100000000081565b6040516001600160e01b0390911681526020016104ff565b6021546105cf906001600160a01b031681565b6031546105cf906001600160a01b031681565b6104f5610af13660046136a5565b611c4e565b6026546105cf906001600160a01b031681565b6108155f81565b6105a7610b1e36600461342f565b611db5565b6039546105cf9061010090046001600160a01b031681565b6105cf610b493660046135e4565b611e5e565b6003546105cf906001600160a01b031681565b610571610b6f366004613244565b60386020525f908152604090205460ff1681565b6109f9610b91366004613244565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b610571610bc83660046136c2565b611e92565b6104f560055481565b610571610be436600461325f565b603260209081525f928352604080842090915290825290205460ff1681565b6104f5610c11366004613244565b611ed6565b5f546105cf906001600160a01b031681565b6104f5601a5481565b6104f5610c3f3660046135e4565b611f6d565b6104f5610c52366004613244565b612011565b5f610c61826120d0565b92915050565b610c88604051806060016040528060328152602001613b34603291396121aa565b6015546001600160a01b03838116911614610cae57610cae610ca98361225a565b61227c565b6001600160a01b038381165f81815260326020908152604080832094871680845294825291829020805460ff191686151590811790915591519182527fc080966e9e93529edc1b244180c245bc60f3d86f1e690a17651a5e428746a8cd91015b60405180910390a3505050565b610d868484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f920191909152506122c192505050565b50505050565b610df98585808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208089028281018201909352888252909350889250879182918501908490808284375f92019190915250869250612411915050565b5050505050565b5f610e3f6040518060400160405280601881526020017f5f73657450726f746f636f6c50617573656428626f6f6c2900000000000000008152506121aa565b60188054831515620100000262ff0000199091161790556040517fd7500633dd3ddd74daa7af62f8c8404c7fe4a81da179998db851696bed004b3890610e8a90841515815260200190565b60405180910390a15090565b5f60175482808203610ec35760405162461bcd60e51b8152600401610eba906136f1565b60405180910390fd5b610ecb6124a0565b601780549085905560408051828152602081018790527f73747d68b346dce1e932bcd238282e7ac84c01569e1f8d0469c222fdc6e9d5a491015b60405180910390a15f9350505b5050919050565b5f610f3b6040518060600160405280602f8152602001613b8f602f91396121aa565b610f468484846124ec565b90505b9392505050565b610f716040518060600160405280602a8152602001613bbe602a91396121aa565b610f7a8261263e565b6001600160a01b0382165f9081526038602052604090205481151560ff909116151503610fa5575050565b6001600160a01b0382165f81815260386020526040808220805460ff191685151590811790915590519092917f1f4df5032f431b9890646a781be28b0d693e581666d1a80be27ae3959069172291a35050565b6110366040518060400160405280601a81526020017f736574506f6f6c4163746976652875696e7439362c626f6f6c290000000000008152506121aa565b6037546001600160601b03908116908316111561107157604051632db8671b60e11b81526001600160601b0383166004820152602401610eba565b6001600160601b03821661109857604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151560ff9091161515036110c857505050565b60028101546040805160ff9092161515825283151560208301526001600160601b038516917f75e42fceb039532886a9d75717e843bfef67fd7f6f91f0fc5b1d48e9ce8a1ba9910160405180910390a2600201805460ff191691151591909117905550565b6001600160a01b031660a09190911b6001600160a01b0319161790565b601b546001600160a01b039081169084908116820361117b5760405162461bcd60e51b8152600401610eba9061373c565b6111836124a0565b61118c8561263e565b601b546001600160a01b0316156111a5576111a561268c565b601b80546001600160a01b0319166001600160a01b038716908117909155601c859055601d84905560408051868152602081018690527f7059037d74ee16b0fb06a4a30f3348dd2635f301f92e373c92899a25a522ef6e910160405180910390a25050505050565b6112156124a0565b61121e8161263e565b5f816001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561125b573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061127f919061377e565b6033549091506001600160a01b038083169116146112df5760405162461bcd60e51b815260206004820152601a60248201527f696e76616c6964207876732076746f6b656e20616464726573730000000000006044820152606401610eba565b6034546040516001600160a01b038085169216907f2565e1579c0926afb7113edbfd85373e85cadaa3e0346f04de19686a2bb86ed1905f90a350603480546001600160a01b0319166001600160a01b0392909216919091179055565b610d868484808060200260200160405190810160405280939291908181526020018383602002808284375f92019190915250506040805160208088028281018201909352878252909350879250869182918501908490808284375f9201919091525061281b92505050565b6113b0828261296b565b5050565b600d81815481106113c3575f80fd5b5f918252602090912001546001600160a01b0316905081565b5f610c6182612a0b565b5f6114086040518060600160405280602c8152602001613c34602c91396121aa565b610f465f858585612aa2565b600a545f906001600160a01b03908116908390811682036114475760405162461bcd60e51b8152600401610eba9061373c565b61144f6124a0565b6114588461263e565b600a80546001600160a01b038681166001600160a01b03198316179092556040519116907f0613b6ee6a04f0d09f390e4d9318894b9f6ac7fd83897cd8d18896ba579c401e90610f059083908890613799565b601a54818082036114ce5760405162461bcd60e51b8152600401610eba906136f1565b6114d66124a0565b601b546001600160a01b0316156114ef576114ef61268c565b601a80549084905560408051828152602081018690527fe81d4ac15e5afa1e708e66664eddc697177423d950d133bda8262d8885e6da3b91015b60405180910390a150505050565b611558604051806060016040528060258152602001613c89602591396121aa565b6037546001600160601b03908116908316111561159357604051632db8671b60e11b81526001600160601b0383166004820152602401610eba565b6001600160601b0382166115ba57604051630203217b60e61b815260040160405180910390fd5b6001600160601b0382165f908152603660205260409020600281015482151561010090910460ff161515036115ee57505050565b60028101546040805161010090920460ff161515825283151560208301526001600160601b038516917f9d2a9183b06e3492f91d3d88ae222e700c8873dd0068f9c3fc783eccb96a1ec4910160405180910390a260020180549115156101000261ff001990921691909117905550565b5f611680604051806060016040528060338152602001613cae603391396121aa565b61168c85858585612aa2565b90505b949350505050565b61169f6124a0565b6116a88161263e565b6033546040516001600160a01b038084169216907ffe7fd0d872def0f65050e9f38fc6691d0c192c694a56f09b04bec5fb2ea61f2b905f90a3603380546001600160a01b0319166001600160a01b0392909216919091179055565b5f610c6182612cbf565b60366020525f9081526040902080548190611727906137b3565b80601f0160208091040260200160405190810160405280929190818152602001828054611753906137b3565b801561179e5780601f106117755761010080835404028352916020019161179e565b820191905f5260205f20905b81548152906001019060200180831161178157829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b5f6117dc604051806060016040528060288152602001613ce1602891396121aa565b610f495f84846124ec565b6026545f906001600160a01b039081169083908116820361181a5760405162461bcd60e51b8152600401610eba9061373c565b6118226124a0565b61182b8461263e565b602680546001600160a01b038681166001600160a01b0319831681179093556040519116917f0f7eb572d1b3053a0a3a33c04151364cf88d163182a5e4e1088cb8e52321e08a91610f05918491613799565b6015545f906001600160a01b03908116908390811682036118b05760405162461bcd60e51b8152600401610eba9061373c565b6118b86124a0565b6118c18461263e565b601580546001600160a01b038681166001600160a01b03198316179092556040519116907fe1ddcb2dab8e5b03cfc8c67a0d5861d91d16f7bd2612fd381faf4541d212c9b290610f059083908890613799565b611935604051806060016040528060278152602001613d09602791396121aa565b6037546001600160601b03908116908416111561197057604051632db8671b60e11b81526001600160601b0384166004820152602401610eba565b5f61197b848461112d565b5f81815260096020526040902080549192509060ff166119ae57604051630665210960e21b815260040160405180910390fd5b82151581600601600c9054906101000a900460ff161515036119d1575050505050565b600681015460408051600160601b90920460ff161515825284151560208301526001600160a01b038616916001600160601b038816917fe40f9c4af130bdb5bd1650ab4bc918dba9d900fa94685f0113e72a6cfe6c5fcc910160405180910390a36006018054921515600160601b0260ff60601b1990931692909217909155505050565b611a936040518060400160405280601b81526020017f736574506f6f6c4c6162656c2875696e7439362c737472696e672900000000008152506121aa565b6037546001600160601b039081169084161115611ace57604051632db8671b60e11b81526001600160601b0384166004820152602401610eba565b6001600160601b038316611af557604051630203217b60e61b815260040160405180910390fd5b5f819003611b165760405163522e397360e11b815260040160405180910390fd5b6001600160601b0383165f90815260366020526040908190209051611b3e90849084906137eb565b60405190819003812090611b539083906137fa565b604051809103902003611b665750505050565b836001600160601b03167f1ebc260ee8077871ff0b70b184ff9dac4ecee8b0f7dcc4f3a3f5068549f5078e825f018585604051611ba593929190613894565b60405180910390a280610df983858361398b565b6025546001600160a01b0390811690829081168203611bea5760405162461bcd60e51b8152600401610eba9061373c565b611bf26124a0565b611bfb8361263e565b602580546001600160a01b038581166001600160a01b03198316179092556040519116907fa5ea5616d5f6dbbaa62fdfcf3856723216eed485c394d9e51ec8e6d40e1d1ac1906115299083908790613799565b6020545f90611c65906001600160a01b0316612d34565b670de0b6b3a76400008210611cae5760405162461bcd60e51b815260206004820152600f60248201526e70657263656e74203e3d203130302560881b6044820152606401610eba565b611cb78461263e565b611cc08361263e565b6020805460218054602280546001600160a01b03198086166001600160a01b038c8116919091179097558316898716179093558690556040519284169316917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e890611d2e9085908a90613799565b60405180910390a17f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac8287604051611d67929190613799565b60405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a15f5b979650505050505050565b611df36040518060400160405280601881526020017f736574466c6173684c6f616e50617573656428626f6f6c2900000000000000008152506121aa565b60395481151560ff909116151503611e085750565b6039546040805160ff9092161515825282151560208301527f79bcfb2700d56371c7684799f99d64cbcd91f1e360f8048a42c9ba534be7c0a8910160405180910390a16039805460ff1916911515919091179055565b6008602052815f5260405f208181548110611e77575f80fd5b5f918252602090912001546001600160a01b03169150829050565b6001600160a01b0382165f90815260296020526040812081836008811115611ebc57611ebc613728565b815260208101919091526040015f205460ff169392505050565b6028545f906001600160a01b0390811690839081168203611f095760405162461bcd60e51b8152600401610eba9061373c565b611f116124a0565b611f1a8461263e565b602880546001600160a01b038681166001600160a01b03198316179092556040519116907f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd490610f059083908890613799565b5f611f76612d8f565b60185460ff16158015611f915750601854610100900460ff16155b611fcd5760405162461bcd60e51b815260206004820152600d60248201526c159052481a5cc81c185d5cd959609a1b6044820152606401610eba565b6015546001600160a01b03163314611ff257611feb600e6016612ddd565b9050610c61565b6001600160a01b0383165f908152601660205260408120839055610f49565b6039545f906001600160a01b036101009091048116908390811682036120495760405162461bcd60e51b8152600401610eba9061373c565b61206a604051806060016040528060228152602001613d30602291396121aa565b6120738461263e565b603980546001600160a01b03868116610100908102610100600160a81b03198416179093556040519290910416907fc4877d82ec0586c93fbd01eb65785e064f0c31b594e7f413e5f16502f25cf27390610f059083908890613799565b5f600554828082036120f45760405162461bcd60e51b8152600401610eba906136f1565b6120fc6124a0565b604080516020808201835286825282518082018452670c7d713b49da00008152835191820190935266b1a2bc2ec500008152815183519293921080612142575082518151115b1561215c57612152600580612ddd565b9550505050610f12565b600580549088905560408051828152602081018a90527f3b9670cf975d26958e754b57098eaa2ac914d8d2a31b83257997b9f346110fd9910160405180910390a15f98975050505050505050565b6028546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906121dc9033908590600401613a45565b602060405180830381865afa1580156121f7573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061221b9190613a68565b6122575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610eba565b50565b5f60095f6122685f8561112d565b81526020019081526020015f209050919050565b805460ff166122575760405162461bcd60e51b81526020600482015260116024820152701b585c9ad95d081b9bdd081b1a5cdd1959607a1b6044820152606401610eba565b6122e2604051806060016040528060298152602001613c60602991396121aa565b8151815181158015906122f457508082145b6123305760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610eba565b5f5b82811015610df95783818151811061234c5761234c613a83565b6020026020010151601f5f87848151811061236957612369613a83565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f20819055508481815181106123a6576123a6613a83565b60200260200101516001600160a01b03167f6f1951b2aad10f3fc81b86d91105b413a5b3f847a34bbc5ce1904201b14438f68583815181106123ea576123ea613a83565b602002602001015160405161240191815260200190565b60405180910390a2600101612332565b612432604051806060016040528060298152602001613b66602991396121aa565b825182515f5b82811015612498575f5b8281101561248f5761248787838151811061245f5761245f613a83565b602002602001015187838151811061247957612479613a83565b602002602001015187612e54565b600101612442565b50600101612438565b505050505050565b5f546001600160a01b031633146124ea5760405162461bcd60e51b815260206004820152600e60248201526d37b7363c9030b236b4b71031b0b760911b6044820152606401610eba565b565b5f60095f6124fa868661112d565b81526020019081526020015f20600501548280820361252b5760405162461bcd60e51b8152600401610eba906136f1565b6037546001600160601b03908116908716111561256657604051632db8671b60e11b81526001600160601b0387166004820152602401610eba565b5f60095f612574898961112d565b81526020019081526020015f20905061258c8161227c565b670de0b6b3a76400008510156125d75760405162461bcd60e51b815260206004820152601060248201526f0d2dcc6cadce8d2ecca40784062ca62760831b6044820152606401610eba565b856001600160a01b0316876001600160601b03167fc1d7bc090f3a87255c2f4e56f66d1b7a49683d279f77921b1701aa5d733ef745836005015488604051612629929190918252602082015260400190565b60405180910390a3600581018590555f611daa565b6001600160a01b0381166122575760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610eba565b601c54158061269c5750601c5443105b156126a357565b6033546040516370a0823160e01b81523060048201526001600160a01b03909116905f9082906370a0823190602401602060405180830381865afa1580156126ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127119190613a97565b9050805f0361271e575050565b5f8061272c43601c54612ef8565b90505f61273b601a5483612f31565b905080841061274c57809250612750565b8392505b601d54831015612761575050505050565b43601c55601b5461277f906001600160a01b03878116911685612f72565b6040518381527ff6d4b8f74d85a6e2d7a50225957b8a6cfec69ad92f5905627260541aa0a5565d9060200160405180910390a1601b5f9054906101000a90046001600160a01b03166001600160a01b031663faa1809e6040518163ffffffff1660e01b81526004015f604051808303815f87803b1580156127fe575f80fd5b505af1158015612810573d5f803e3d5ffd5b505050505050505050565b61283c604051806060016040528060298152602001613be8602991396121aa565b81518151811580159061284e57508082145b61288a5760405162461bcd60e51b815260206004820152600d60248201526c1a5b9d985b1a59081a5b9c1d5d609a1b6044820152606401610eba565b5f5b82811015610df9578381815181106128a6576128a6613a83565b602002602001015160275f8784815181106128c3576128c3613a83565b60200260200101516001600160a01b03166001600160a01b031681526020019081526020015f208190555084818151811061290057612900613a83565b60200260200101516001600160a01b03167f9e0ad9cee10bdf36b7fbd38910c0bdff0f275ace679b45b922381c2723d676f885838151811061294457612944613a83565b602002602001015160405161295b91815260200190565b60405180910390a260010161288c565b61298c604051806060016040528060238152602001613c11602391396121aa565b6015546001600160a01b038381169116146129ad576129ad610ca98361225a565b6001600160a01b0382165f818152602d6020908152604091829020805460ff191685151590811790915591519182527f03561d5280ebb02280893b1d60978e4a27e7654a149c5d0e7c2cf65389ce1694910160405180910390a25050565b6004545f906001600160a01b0390811690839081168203612a3e5760405162461bcd60e51b8152600401610eba9061373c565b612a466124a0565b612a4f8461263e565b600480546001600160a01b038681166001600160a01b03198316179092556040519116907fd52b2b9b7e9ee655fcb95d2e5b9e0c9f69e7ef2b8e9d2d0ea78402d576d22e2290610f059083908890613799565b5f612aac8461263e565b6037546001600160601b039081169086161115612ae757604051632db8671b60e11b81526001600160601b0386166004820152602401610eba565b5f60095f612af5888861112d565b81526020019081526020015f209050612b0d8161227c565b670de0b6b3a7640000841115612b3157612b2960066008612ddd565b91505061168f565b8315801590612bab57506004805460405163fc57d4df60e01b81526001600160a01b038881169382019390935291169063fc57d4df90602401602060405180830381865afa158015612b85573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612ba99190613a97565b155b15612bbc57612b29600d6009612ddd565b670de0b6b3a7640000831115612bd857612b2960146019612ddd565b83831015612bec57612b296014601a612ddd565b6001810154848114612c4f576001820185905560408051828152602081018790526001600160a01b038816916001600160601b038a16917f0d1a615379dc62cec7bc63b7e313a07ed659918f4ad3720b3af8041b305146f2910160405180910390a35b6004820154848114612cb2576004830185905560408051828152602081018790526001600160a01b038916916001600160601b038b16917fc90f7b48c299a8d58b0b9e2756e27773c6fb1daab159af052d6c5b791bc7eef7910160405180910390a35b5f98975050505050505050565b5f612cc86124a0565b612cd18261263e565b603180546001600160a01b038481166001600160a01b03198316179092556040519116907fcb20dab7409e4fb972d9adccb39530520b226ce6940d85c9523a499b950b6ea390612d249083908690613799565b60405180910390a15f9392505050565b5f546001600160a01b031633148061221b5750336001600160a01b038216146122575760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610eba565b60185462010000900460ff16156124ea5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610eba565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836014811115612e1157612e11613728565b83601a811115612e2357612e23613728565b6040805192835260208301919091525f9082015260600160405180910390a1826014811115610f4957610f49613728565b612e60610ca98461225a565b6001600160a01b0383165f9081526029602052604081208291846008811115612e8b57612e8b613728565b815260208101919091526040015f20805460ff1916911515919091179055816008811115612ebb57612ebb613728565b836001600160a01b03167f35007a986bcd36d2f73fc7f1b73762e12eadb4406dd163194950fd3b5a6a827d83604051610d0e911515815260200190565b5f610f498383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250612fc9565b5f610f4983836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250612ff7565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052612fc4908490613050565b505050565b5f8184841115612fec5760405162461bcd60e51b8152600401610eba9190613aae565b50610f468385613ad4565b5f831580613003575082155b1561300f57505f610f49565b5f61301a8486613ae7565b9050836130278683613afe565b1483906130475760405162461bcd60e51b8152600401610eba9190613aae565b50949350505050565b5f6130a4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166131239092919063ffffffff16565b905080515f14806130c45750808060200190518101906130c49190613a68565b612fc45760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610eba565b6060610f4684845f85855f80866001600160a01b031685876040516131489190613b1d565b5f6040518083038185875af1925050503d805f8114613182576040519150601f19603f3d011682016040523d82523d5f602084013e613187565b606091505b5091509150611daa87838387606083156132015782515f036131fa576001600160a01b0385163b6131fa5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610eba565b508161168f565b61168f83838151156132165781518083602001fd5b8060405162461bcd60e51b8152600401610eba9190613aae565b6001600160a01b0381168114612257575f80fd5b5f60208284031215613254575f80fd5b8135610f4981613230565b5f8060408385031215613270575f80fd5b823561327b81613230565b9150602083013561328b81613230565b809150509250929050565b5f602082840312156132a6575f80fd5b5035919050565b8015158114612257575f80fd5b5f805f606084860312156132cc575f80fd5b83356132d781613230565b925060208401356132e781613230565b915060408401356132f7816132ad565b809150509250925092565b5f8083601f840112613312575f80fd5b50813567ffffffffffffffff811115613329575f80fd5b6020830191508360208260051b8501011115613343575f80fd5b9250929050565b5f805f806040858703121561335d575f80fd5b843567ffffffffffffffff80821115613374575f80fd5b61338088838901613302565b90965094506020870135915080821115613398575f80fd5b506133a587828801613302565b95989497509550505050565b5f805f805f606086880312156133c5575f80fd5b853567ffffffffffffffff808211156133dc575f80fd5b6133e889838a01613302565b90975095506020880135915080821115613400575f80fd5b5061340d88828901613302565b9094509250506040860135613421816132ad565b809150509295509295909350565b5f6020828403121561343f575f80fd5b8135610f49816132ad565b80356001600160601b0381168114613460575f80fd5b919050565b5f805f60608486031215613477575f80fd5b6134808461344a565b9250602084013561349081613230565b929592945050506040919091013590565b5f80604083850312156134b2575f80fd5b82356134bd81613230565b9150602083013561328b816132ad565b5f80604083850312156134de575f80fd5b6134bd8361344a565b5f80604083850312156134f8575f80fd5b61327b8361344a565b5f805f60608486031215613513575f80fd5b833561351e81613230565b95602085013595506040909401359392505050565b5f805f8060808587031215613546575f80fd5b61354f8561344a565b9350602085013561355f81613230565b93969395505050506040820135916060013590565b5f60208284031215613584575f80fd5b610f498261344a565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f6135cd606083018661358d565b931515602083015250901515604090910152919050565b5f80604083850312156135f5575f80fd5b823561360081613230565b946020939093013593505050565b5f805f60608486031215613620575f80fd5b6132d78461344a565b5f805f6040848603121561363b575f80fd5b6136448461344a565b9250602084013567ffffffffffffffff80821115613660575f80fd5b818601915086601f830112613673575f80fd5b813581811115613681575f80fd5b876020828501011115613692575f80fd5b6020830194508093505050509250925092565b5f805f606084860312156136b7575f80fd5b833561348081613230565b5f80604083850312156136d3575f80fd5b82356136de81613230565b915060208301356009811061328b575f80fd5b6020808252601e908201527f6f6c642076616c75652069732073616d65206173206e65772076616c75650000604082015260600190565b634e487b7160e01b5f52602160045260245ffd5b60208082526022908201527f6f6c6420616464726573732069732073616d65206173206e6577206164647265604082015261737360f01b606082015260800190565b5f6020828403121561378e575f80fd5b8151610f4981613230565b6001600160a01b0392831681529116602082015260400190565b600181811c908216806137c757607f821691505b6020821081036137e557634e487b7160e01b5f52602260045260245ffd5b50919050565b818382375f9101908152919050565b5f808354613807816137b3565b6001828116801561381f576001811461383457613860565b60ff1984168752821515830287019450613860565b875f526020805f205f5b858110156138575781548a82015290840190820161383e565b50505082870194505b50929695505050505050565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b604081525f8085546138a5816137b3565b806040860152606060018084165f81146138c657600181146138e257613911565b60ff1985166060890152606084151560051b8901019550613911565b8a5f526020805f205f5b868110156139075781548b82018701529084019082016138ec565b8a01606001975050505b5050505050828103602084015261392981858761386c565b9695505050505050565b634e487b7160e01b5f52604160045260245ffd5b601f821115612fc457805f5260205f20601f840160051c8101602085101561396c5750805b601f840160051c820191505b81811015610df9575f8155600101613978565b67ffffffffffffffff8311156139a3576139a3613933565b6139b7836139b183546137b3565b83613947565b5f601f8411600181146139e8575f85156139d15750838201355b5f19600387901b1c1916600186901b178355610df9565b5f83815260208120601f198716915b82811015613a1757868501358255602094850194600190920191016139f7565b5086821015613a33575f1960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6001600160a01b03831681526040602082018190525f90610f469083018461358d565b5f60208284031215613a78575f80fd5b8151610f49816132ad565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215613aa7575f80fd5b5051919050565b602081525f610f49602083018461358d565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610c6157610c61613ac0565b8082028115828204841417610c6157610c61613ac0565b5f82613b1857634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f92019182525091905056fe5f736574466f726365644c69717569646174696f6e466f725573657228616464726573732c616464726573732c626f6f6c295f736574416374696f6e7350617573656428616464726573735b5d2c75696e74385b5d2c626f6f6c297365744c69717569646174696f6e496e63656e746976652875696e7439362c616464726573732c75696e743235362973657457686974654c697374466c6173684c6f616e4163636f756e7428616464726573732c626f6f6c295f7365744d61726b6574537570706c794361707328616464726573735b5d2c75696e743235365b5d295f736574466f726365644c69717569646174696f6e28616464726573732c626f6f6c29736574436f6c6c61746572616c466163746f7228616464726573732c75696e743235362c75696e74323536295f7365744d61726b6574426f72726f774361707328616464726573735b5d2c75696e743235365b5d29736574416c6c6f77436f7265506f6f6c46616c6c6261636b2875696e7439362c626f6f6c29736574436f6c6c61746572616c466163746f722875696e7439362c616464726573732c75696e743235362c75696e74323536297365744c69717569646174696f6e496e63656e7469766528616464726573732c75696e74323536297365744973426f72726f77416c6c6f7765642875696e7439362c616464726573732c626f6f6c29736574446576696174696f6e426f756e6465644f7261636c65286164647265737329a2646970667358221220565945c5e9c23268c820f53390cd21154914aeaa407c9ffe8251b3b5175293a464736f6c63430008190033", "devdoc": { "author": "Venus", "details": "This facet contains all the setters for the states", @@ -2757,6 +2808,14 @@ "_0": "uint256 0=success, otherwise a failure. (See ErrorReporter for details)" } }, + "setDeviationBoundedOracle(address)": { + "params": { + "newDeviationBoundedOracle": "The new DeviationBoundedOracle contract" + }, + "returns": { + "_0": "uint256 0=success, otherwise a failure" + } + }, "setFlashLoanPaused(bool)": { "custom:access": "Only Governance", "custom:event": "Emits FlashLoanPauseChanged event", @@ -2998,6 +3057,9 @@ "NewComptrollerLens(address,address)": { "notice": "Emitted when ComptrollerLens address is changed" }, + "NewDeviationBoundedOracle(address,address)": { + "notice": "Emitted when deviation bounded oracle is changed" + }, "NewLiquidationIncentive(uint96,address,uint256,uint256)": { "notice": "Emitted when liquidation incentive for a market in a pool is changed by admin" }, @@ -3145,6 +3207,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "flashLoanPaused()": { "notice": "Whether flash loans are paused system-wide" }, @@ -3208,6 +3273,9 @@ "setCollateralFactor(uint96,address,uint256,uint256)": { "notice": "Sets the collateral factor and liquidation threshold for a market in the specified pool." }, + "setDeviationBoundedOracle(address)": { + "notice": "Sets the DeviationBoundedOracle for conservative CF-path pricing" + }, "setFlashLoanPaused(bool)": { "notice": "Pause or unpause flash loans system-wide" }, @@ -3302,7 +3370,7 @@ "storageLayout": { "storage": [ { - "astId": 1677, + "astId": 9780, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "admin", "offset": 0, @@ -3310,7 +3378,7 @@ "type": "t_address" }, { - "astId": 1680, + "astId": 9783, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "pendingAdmin", "offset": 0, @@ -3318,7 +3386,7 @@ "type": "t_address" }, { - "astId": 1683, + "astId": 9786, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "comptrollerImplementation", "offset": 0, @@ -3326,7 +3394,7 @@ "type": "t_address" }, { - "astId": 1686, + "astId": 9789, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "pendingComptrollerImplementation", "offset": 0, @@ -3334,15 +3402,15 @@ "type": "t_address" }, { - "astId": 1693, + "astId": 9796, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)992" + "type": "t_contract(ResilientOracleInterface)8467" }, { - "astId": 1696, + "astId": 9799, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "closeFactorMantissa", "offset": 0, @@ -3350,7 +3418,7 @@ "type": "t_uint256" }, { - "astId": 1699, + "astId": 9802, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -3358,7 +3426,7 @@ "type": "t_uint256" }, { - "astId": 1702, + "astId": 9805, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "maxAssets", "offset": 0, @@ -3366,23 +3434,23 @@ "type": "t_uint256" }, { - "astId": 1709, + "astId": 9812, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)" }, { - "astId": 1743, + "astId": 9846, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)" }, { - "astId": 1746, + "astId": 9849, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "pauseGuardian", "offset": 0, @@ -3390,7 +3458,7 @@ "type": "t_address" }, { - "astId": 1749, + "astId": 9852, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_mintGuardianPaused", "offset": 20, @@ -3398,7 +3466,7 @@ "type": "t_bool" }, { - "astId": 1752, + "astId": 9855, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_borrowGuardianPaused", "offset": 21, @@ -3406,7 +3474,7 @@ "type": "t_bool" }, { - "astId": 1755, + "astId": 9858, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "transferGuardianPaused", "offset": 22, @@ -3414,7 +3482,7 @@ "type": "t_bool" }, { - "astId": 1758, + "astId": 9861, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "seizeGuardianPaused", "offset": 23, @@ -3422,7 +3490,7 @@ "type": "t_bool" }, { - "astId": 1763, + "astId": 9866, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "mintGuardianPaused", "offset": 0, @@ -3430,7 +3498,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1768, + "astId": 9871, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "borrowGuardianPaused", "offset": 0, @@ -3438,15 +3506,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1780, + "astId": 9883, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)32634)dyn_storage" + "type": "t_array(t_contract(VToken)58633)dyn_storage" }, { - "astId": 1783, + "astId": 9886, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusRate", "offset": 0, @@ -3454,7 +3522,7 @@ "type": "t_uint256" }, { - "astId": 1788, + "astId": 9891, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusSpeeds", "offset": 0, @@ -3462,23 +3530,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1794, + "astId": 9897, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1800, + "astId": 9903, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1807, + "astId": 9910, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusSupplierIndex", "offset": 0, @@ -3486,7 +3554,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1814, + "astId": 9917, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusBorrowerIndex", "offset": 0, @@ -3494,7 +3562,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1819, + "astId": 9922, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusAccrued", "offset": 0, @@ -3502,15 +3570,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1823, + "astId": 9926, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)25733" + "type": "t_contract(VAIControllerInterface)51683" }, { - "astId": 1828, + "astId": 9931, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "mintedVAIs", "offset": 0, @@ -3518,7 +3586,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1831, + "astId": 9934, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "vaiMintRate", "offset": 0, @@ -3526,7 +3594,7 @@ "type": "t_uint256" }, { - "astId": 1834, + "astId": 9937, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "mintVAIGuardianPaused", "offset": 0, @@ -3534,7 +3602,7 @@ "type": "t_bool" }, { - "astId": 1836, + "astId": 9939, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "repayVAIGuardianPaused", "offset": 1, @@ -3542,7 +3610,7 @@ "type": "t_bool" }, { - "astId": 1839, + "astId": 9942, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "protocolPaused", "offset": 2, @@ -3550,7 +3618,7 @@ "type": "t_bool" }, { - "astId": 1842, + "astId": 9945, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusVAIRate", "offset": 0, @@ -3558,7 +3626,7 @@ "type": "t_uint256" }, { - "astId": 1848, + "astId": 9951, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusVAIVaultRate", "offset": 0, @@ -3566,7 +3634,7 @@ "type": "t_uint256" }, { - "astId": 1850, + "astId": 9953, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "vaiVaultAddress", "offset": 0, @@ -3574,7 +3642,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9955, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "releaseStartBlock", "offset": 0, @@ -3582,7 +3650,7 @@ "type": "t_uint256" }, { - "astId": 1854, + "astId": 9957, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "minReleaseAmount", "offset": 0, @@ -3590,7 +3658,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9963, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "borrowCapGuardian", "offset": 0, @@ -3598,7 +3666,7 @@ "type": "t_address" }, { - "astId": 1865, + "astId": 9968, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "borrowCaps", "offset": 0, @@ -3606,7 +3674,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1871, + "astId": 9974, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "treasuryGuardian", "offset": 0, @@ -3614,7 +3682,7 @@ "type": "t_address" }, { - "astId": 1874, + "astId": 9977, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "treasuryAddress", "offset": 0, @@ -3622,7 +3690,7 @@ "type": "t_address" }, { - "astId": 1877, + "astId": 9980, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "treasuryPercent", "offset": 0, @@ -3630,7 +3698,7 @@ "type": "t_uint256" }, { - "astId": 1885, + "astId": 9988, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusContributorSpeeds", "offset": 0, @@ -3638,7 +3706,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9993, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "lastContributorBlock", "offset": 0, @@ -3646,7 +3714,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1895, + "astId": 9998, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "liquidatorContract", "offset": 0, @@ -3654,15 +3722,15 @@ "type": "t_address" }, { - "astId": 1901, + "astId": 10004, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1660" + "type": "t_contract(ComptrollerLensInterface)9761" }, { - "astId": 1909, + "astId": 10012, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "supplyCaps", "offset": 0, @@ -3670,7 +3738,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1915, + "astId": 10018, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "accessControl", "offset": 0, @@ -3678,7 +3746,7 @@ "type": "t_address" }, { - "astId": 1922, + "astId": 10025, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_actionPaused", "offset": 0, @@ -3686,7 +3754,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1930, + "astId": 10033, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusBorrowSpeeds", "offset": 0, @@ -3694,7 +3762,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1935, + "astId": 10038, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "venusSupplySpeeds", "offset": 0, @@ -3702,7 +3770,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1945, + "astId": 10048, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "approvedDelegates", "offset": 0, @@ -3710,7 +3778,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1953, + "astId": 10056, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -3718,23 +3786,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1972, + "astId": 10075, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)" }, { - "astId": 1977, + "astId": 10080, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)" }, { - "astId": 1980, + "astId": 10083, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "_facetAddresses", "offset": 0, @@ -3742,15 +3810,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1987, + "astId": 10090, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)22911" + "type": "t_contract(IPrime)42902" }, { - "astId": 1997, + "astId": 10100, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -3758,7 +3826,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 2003, + "astId": 10106, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "xvs", "offset": 0, @@ -3766,7 +3834,7 @@ "type": "t_address" }, { - "astId": 2006, + "astId": 10109, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "xvsVToken", "offset": 0, @@ -3774,7 +3842,7 @@ "type": "t_address" }, { - "astId": 2028, + "astId": 10131, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "userPoolId", "offset": 0, @@ -3782,15 +3850,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2034, + "astId": 10137, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)2023_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)10126_storage)" }, { - "astId": 2037, + "astId": 10140, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "lastPoolId", "offset": 0, @@ -3798,7 +3866,7 @@ "type": "t_uint96" }, { - "astId": 2045, + "astId": 10148, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "authorizedFlashLoan", "offset": 0, @@ -3806,12 +3874,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2048, + "astId": 10151, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 10158, + "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)8437" } ], "types": { @@ -3832,8 +3908,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)32634)dyn_storage": { - "base": "t_contract(VToken)32634", + "t_array(t_contract(VToken)58633)dyn_storage": { + "base": "t_contract(VToken)58633", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -3848,37 +3924,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1660": { + "t_contract(ComptrollerLensInterface)9761": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)22911": { + "t_contract(IDeviationBoundedOracle)8437": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)42902": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)992": { + "t_contract(ResilientOracleInterface)8467": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)25733": { + "t_contract(VAIControllerInterface)51683": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)32634": { + "t_contract(VToken)58633": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)32634)dyn_storage" + "value": "t_array(t_contract(VToken)58633)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -3908,19 +3989,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1967_storage" + "value": "t_struct(FacetFunctionSelectors)10070_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1775_storage" + "value": "t_struct(VenusMarketState)9878_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -3936,12 +4017,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1961_storage" + "value": "t_struct(FacetAddressAndPosition)10064_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -3950,31 +4031,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)2023_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)10126_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)2023_storage" + "value": "t_struct(PoolData)10126_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11427", + "key": "t_userDefinedValueType(PoolMarketId)19777", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1736_storage" + "value": "t_struct(Market)9839_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1961_storage": { + "t_struct(FacetAddressAndPosition)10064_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1958, + "astId": 10061, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "facetAddress", "offset": 0, @@ -3982,7 +4063,7 @@ "type": "t_address" }, { - "astId": 1960, + "astId": 10063, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "functionSelectorPosition", "offset": 20, @@ -3992,12 +4073,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1967_storage": { + "t_struct(FacetFunctionSelectors)10070_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1964, + "astId": 10067, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "functionSelectors", "offset": 0, @@ -4005,7 +4086,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1966, + "astId": 10069, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "facetAddressPosition", "offset": 0, @@ -4015,12 +4096,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1736_storage": { + "t_struct(Market)9839_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1712, + "astId": 9815, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isListed", "offset": 0, @@ -4028,7 +4109,7 @@ "type": "t_bool" }, { - "astId": 1715, + "astId": 9818, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "collateralFactorMantissa", "offset": 0, @@ -4036,7 +4117,7 @@ "type": "t_uint256" }, { - "astId": 1720, + "astId": 9823, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "accountMembership", "offset": 0, @@ -4044,7 +4125,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1723, + "astId": 9826, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isVenus", "offset": 0, @@ -4052,7 +4133,7 @@ "type": "t_bool" }, { - "astId": 1726, + "astId": 9829, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "liquidationThresholdMantissa", "offset": 0, @@ -4060,7 +4141,7 @@ "type": "t_uint256" }, { - "astId": 1729, + "astId": 9832, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -4068,7 +4149,7 @@ "type": "t_uint256" }, { - "astId": 1732, + "astId": 9835, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "poolId", "offset": 0, @@ -4076,7 +4157,7 @@ "type": "t_uint96" }, { - "astId": 1735, + "astId": 9838, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isBorrowAllowed", "offset": 12, @@ -4086,12 +4167,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)2023_storage": { + "t_struct(PoolData)10126_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 2012, + "astId": 10115, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "label", "offset": 0, @@ -4099,7 +4180,7 @@ "type": "t_string_storage" }, { - "astId": 2016, + "astId": 10119, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "vTokens", "offset": 0, @@ -4107,7 +4188,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 2019, + "astId": 10122, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "isActive", "offset": 0, @@ -4115,7 +4196,7 @@ "type": "t_bool" }, { - "astId": 2022, + "astId": 10125, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "allowCorePoolFallback", "offset": 1, @@ -4125,12 +4206,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1775_storage": { + "t_struct(VenusMarketState)9878_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1771, + "astId": 9874, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "index", "offset": 0, @@ -4138,7 +4219,7 @@ "type": "t_uint224" }, { - "astId": 1774, + "astId": 9877, "contract": "contracts/Comptroller/Diamond/facets/SetterFacet.sol:SetterFacet", "label": "block", "offset": 28, @@ -4168,7 +4249,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11427": { + "t_userDefinedValueType(PoolMarketId)19777": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bsctestnet/SnapshotLens.json b/deployments/bsctestnet/SnapshotLens.json index ad3dc919b..2fcc619df 100644 --- a/deployments/bsctestnet/SnapshotLens.json +++ b/deployments/bsctestnet/SnapshotLens.json @@ -1,5 +1,5 @@ { - "address": "0xBe9174A13577B016280aEc20a3b369C5BA272241", + "address": "0x88bB0AF511B5AB585460E7c36150Db82c28D9E5E", "abi": [ { "inputs": [ @@ -65,7 +65,17 @@ }, { "internalType": "uint256", - "name": "assetPrice", + "name": "spotPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "boundedCollateralPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "boundedDebtPrice", "type": "uint256" }, { @@ -171,7 +181,17 @@ }, { "internalType": "uint256", - "name": "assetPrice", + "name": "spotPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "boundedCollateralPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "boundedDebtPrice", "type": "uint256" }, { @@ -238,28 +258,28 @@ "type": "function" } ], - "transactionHash": "0x01eba69df79132c1433edee1f99d3de1871c54c8eb4f782c2fb19157124e1caf", + "transactionHash": "0x16bf76315330ee1edbf6a8c195e1b2269111476e71b675c5976b4abc05833058", "receipt": { "to": null, - "from": "0xe2a089cA69a90f1E27E723EFD339Cff4c4701AcC", - "contractAddress": "0xBe9174A13577B016280aEc20a3b369C5BA272241", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0x88bB0AF511B5AB585460E7c36150Db82c28D9E5E", "transactionIndex": 0, - "gasUsed": "1032734", + "gasUsed": "1101280", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3f6dda109f5681c14f9a7461ea88f41f786910dd14ed94bf72666d7e2787067e", - "transactionHash": "0x01eba69df79132c1433edee1f99d3de1871c54c8eb4f782c2fb19157124e1caf", + "blockHash": "0x95bf337f389a1abf6ba8b32d32851ad91a2cab40baad8e5dbc100e455275b9d0", + "transactionHash": "0x16bf76315330ee1edbf6a8c195e1b2269111476e71b675c5976b4abc05833058", "logs": [], - "blockNumber": 65911682, - "cumulativeGasUsed": "1032734", + "blockNumber": 102774759, + "cumulativeGasUsed": "1101280", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 3, - "solcInputHash": "b5b7dc739452db3c934f056e8d1be588", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getAccountSnapshot\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"assetName\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowsInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"assetPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"accruedInterest\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isACollateral\",\"type\":\"bool\"}],\"internalType\":\"struct SnapshotLens.AccountSnapshot[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getAccountSnapshot\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"assetName\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowsInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"assetPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"accruedInterest\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isACollateral\",\"type\":\"bool\"}],\"internalType\":\"struct SnapshotLens.AccountSnapshot\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"isACollateral\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/SnapshotLens.sol\":\"SnapshotLens\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0xb8de7a0684411bc301a5a4a3411656c712a7f94668b3ec617ec27b37cf6cd0ea\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/SnapshotLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { ExponentialNoError } from \\\"../Utils/ExponentialNoError.sol\\\";\\nimport { ComptrollerInterface } from \\\"../Comptroller/ComptrollerInterface.sol\\\";\\nimport { VBep20 } from \\\"../Tokens/VTokens/VBep20.sol\\\";\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract SnapshotLens is ExponentialNoError {\\n struct AccountSnapshot {\\n address account;\\n string assetName;\\n address vTokenAddress;\\n address underlyingAssetAddress;\\n uint256 supply;\\n uint256 supplyInUsd;\\n uint256 collateral;\\n uint256 borrows;\\n uint256 borrowsInUsd;\\n uint256 assetPrice;\\n uint256 accruedInterest;\\n uint vTokenDecimals;\\n uint underlyingDecimals;\\n uint exchangeRate;\\n bool isACollateral;\\n }\\n\\n /** Snapshot calculation **/\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account snapshot.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountSnapshotLocalVars {\\n uint collateral;\\n uint vTokenBalance;\\n uint borrowBalance;\\n uint borrowsInUsd;\\n uint balanceOfUnderlying;\\n uint supplyInUsd;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n bool isACollateral;\\n }\\n\\n function getAccountSnapshot(\\n address payable account,\\n address comptrollerAddress\\n ) public returns (AccountSnapshot[] memory) {\\n // For each asset the account is in\\n VToken[] memory assets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n AccountSnapshot[] memory accountSnapshots = new AccountSnapshot[](assets.length);\\n for (uint256 i = 0; i < assets.length; ++i) {\\n accountSnapshots[i] = getAccountSnapshot(account, comptrollerAddress, assets[i]);\\n }\\n return accountSnapshots;\\n }\\n\\n function isACollateral(address account, address asset, address comptrollerAddress) public view returns (bool) {\\n VToken[] memory assetsAsCollateral = ComptrollerInterface(comptrollerAddress).getAssetsIn(account);\\n for (uint256 j = 0; j < assetsAsCollateral.length; ++j) {\\n if (address(assetsAsCollateral[j]) == asset) {\\n return true;\\n }\\n }\\n\\n return false;\\n }\\n\\n function getAccountSnapshot(\\n address payable account,\\n address comptrollerAddress,\\n VToken vToken\\n ) public returns (AccountSnapshot memory) {\\n AccountSnapshotLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n\\n // Read the balances and exchange rate from the vToken\\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = vToken.getAccountSnapshot(account);\\n require(oErr == 0, \\\"Snapshot Error\\\");\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n uint collateralFactorMantissa = ComptrollerInterface(comptrollerAddress).getEffectiveLtvFactor(\\n account,\\n address(vToken),\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n vars.collateralFactor = Exp({ mantissa: collateralFactorMantissa });\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = ComptrollerInterface(comptrollerAddress).oracle().getUnderlyingPrice(\\n address(vToken)\\n );\\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n\\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), vars.oraclePrice);\\n\\n //Collateral = tokensToDenom * vTokenBalance\\n vars.collateral = mul_ScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\\n\\n vars.balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n vars.supplyInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.balanceOfUnderlying);\\n\\n vars.borrowsInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.borrowBalance);\\n\\n address underlyingAssetAddress;\\n uint underlyingDecimals;\\n\\n if (compareStrings(vToken.symbol(), \\\"vBNB\\\")) {\\n underlyingAssetAddress = address(0);\\n underlyingDecimals = 18;\\n } else {\\n VBep20 vBep20 = VBep20(address(vToken));\\n underlyingAssetAddress = vBep20.underlying();\\n underlyingDecimals = IERC20Metadata(vBep20.underlying()).decimals();\\n }\\n\\n vars.isACollateral = isACollateral(account, address(vToken), comptrollerAddress);\\n\\n return\\n AccountSnapshot({\\n account: account,\\n assetName: vToken.name(),\\n vTokenAddress: address(vToken),\\n underlyingAssetAddress: underlyingAssetAddress,\\n supply: vars.balanceOfUnderlying,\\n supplyInUsd: vars.supplyInUsd,\\n collateral: vars.collateral,\\n borrows: vars.borrowBalance,\\n borrowsInUsd: vars.borrowsInUsd,\\n assetPrice: vars.oraclePriceMantissa,\\n accruedInterest: vToken.borrowIndex(),\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n exchangeRate: vToken.exchangeRateCurrent(),\\n isACollateral: vars.isACollateral\\n });\\n }\\n\\n // utilities\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0xba1f9da2cf4ef10985838cc1d7cfc31fc433bb058ef953ca641cb13db69f8954\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VBep20.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VBep20Interface, VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\n\\n/**\\n * @title Venus's VBep20 Contract\\n * @notice vTokens which wrap an ERC-20 underlying\\n * @author Venus\\n */\\ncontract VBep20 is VToken, VBep20Interface {\\n using SafeERC20 for IERC20;\\n\\n /*** User Interface ***/\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n // @custom:event Emits Mint event\\n function mint(uint mintAmount) external returns (uint) {\\n (uint err, ) = mintInternal(mintAmount);\\n return err;\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n // @custom:event Emits MintBehalf event\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\\n (uint err, ) = mintBehalfInternal(receiver, mintAmount);\\n return err;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Redeem event on success\\n // @custom:event Emits Transfer event on success\\n // @custom:event Emits RedeemFee when fee is charged by the treasury\\n function redeem(uint redeemTokens) external returns (uint) {\\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\\n }\\n\\n /**\\n * @notice Sender redeems assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The user on behalf of whom to redeem\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Redeem event on success\\n // @custom:event Emits Transfer event on success\\n // @custom:event Emits RedeemFee when fee is charged by the treasury\\n function redeemBehalf(address redeemer, uint redeemTokens) external returns (uint) {\\n require(comptroller.approvedDelegates(redeemer, msg.sender), \\\"not an approved delegate\\\");\\n\\n return redeemInternal(redeemer, payable(msg.sender), redeemTokens);\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to redeem\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Redeem event on success\\n // @custom:event Emits Transfer event on success\\n // @custom:event Emits RedeemFee when fee is charged by the treasury\\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer, on behalf of whom to redeem\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Redeem event on success\\n // @custom:event Emits Transfer event on success\\n // @custom:event Emits RedeemFee when fee is charged by the treasury\\n function redeemUnderlyingBehalf(address redeemer, uint redeemAmount) external returns (uint) {\\n require(comptroller.approvedDelegates(redeemer, msg.sender), \\\"not an approved delegate\\\");\\n\\n return redeemUnderlyingInternal(redeemer, payable(msg.sender), redeemAmount);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Borrow event on success\\n function borrow(uint borrowAmount) external returns (uint) {\\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\\n }\\n\\n /**\\n * @notice Sender borrows assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the borrower using `comptroller.updateDelegate`\\n * @param borrower The borrower, on behalf of whom to borrow.\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Borrow event on success\\n function borrowBehalf(address borrower, uint borrowAmount) external returns (uint) {\\n require(comptroller.approvedDelegates(borrower, msg.sender), \\\"not an approved delegate\\\");\\n return borrowInternal(borrower, payable(msg.sender), borrowAmount);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits RepayBorrow event on success\\n function repayBorrow(uint repayAmount) external returns (uint) {\\n (uint err, ) = repayBorrowInternal(repayAmount);\\n return err;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits RepayBorrow event on success\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\\n (uint err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\\n return err;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emit LiquidateBorrow event on success\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint) {\\n (uint err, ) = liquidateBorrowInternal(borrower, repayAmount, vTokenCollateral);\\n return err;\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying tokens to add as reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesAdded event\\n function _addReserves(uint addAmount) external returns (uint) {\\n return _addReservesInternal(addAmount);\\n }\\n\\n /**\\n * @notice Initialize the new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ BEP-20 name of this token\\n * @param symbol_ BEP-20 symbol of this token\\n * @param decimals_ BEP-20 decimal precision of this token\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n // VToken initialize does the bulk of the work\\n super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20(underlying).totalSupply();\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function doTransferIn(address from, uint256 amount) internal virtual override returns (uint256) {\\n IERC20 token = IERC20(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n // Return the amount that was *actually* transferred\\n return balanceAfter - balanceBefore;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function doTransferOut(address payable to, uint256 amount) internal virtual override {\\n IERC20 token = IERC20(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying tokens owned by this contract\\n */\\n function getCashPrior() internal view override returns (uint) {\\n return IERC20(underlying).balanceOf(address(this));\\n }\\n}\\n\",\"keccak256\":\"0x5c7901e5f3c83c48a62b9f4a4287ad51db9963b7a27d72295090759bd29aa7a9\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint vTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n if (cashPrior < totalReservesNew) {\\n _reduceReservesFresh(cashPrior);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintBelahfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, 1e18);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(address borrower, address payable receiver, uint borrowAmount) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // totalReserves - reduceAmount\\n uint totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModelV8 oldInterestRateModel;\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0x24ceb1a473f6e51ec1a7085b0a5b734c0104001bfddd3165b672e3ad2d5467d4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1409d08c6eb3181b2a62913e1c9457a57ce747c062dbf89d6aa568e316add079\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0xad8d795a0011f59304cae938f062a72a998710c01db94f9a813b4f2f00c9534b\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0xf03faf89ad2689a29f0d456c1add258bc09bcf484840170154a32e129500818e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506111b28061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061003f575f3560e01c806332221cf614610043578063e6bf1d3a1461006c578063ebdf591a1461008f575b5f80fd5b610056610051366004610cb5565b6100af565b6040516100639190610dfa565b60405180910390f35b61007f61007a366004610e5c565b6101cc565b6040519015158152602001610063565b6100a261009d366004610e5c565b610299565b6040516100639190610ea4565b60605f826001600160a01b031663b0772d0b6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156100ed573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526101149190810190610efb565b90505f815167ffffffffffffffff81111561013157610131610eb6565b60405190808252806020026020018201604052801561016a57816020015b610157610b6e565b81526020019060019003908161014f5790505b5090505f5b82518110156101c15761019c868685848151811061018f5761018f610fa8565b6020026020010151610299565b8282815181106101ae576101ae610fa8565b602090810291909101015260010161016f565b509150505b92915050565b604051632aff3bff60e21b81526001600160a01b0384811660048301525f91829184169063abfceffc906024015f60405180830381865afa158015610213573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261023a9190810190610efb565b90505f5b815181101561028c57846001600160a01b031682828151811061026357610263610fa8565b60200260200101516001600160a01b03160361028457600192505050610292565b60010161023e565b505f9150505b9392505050565b6102a1610b6e565b6102a9610bf3565b6040516361bfb47160e11b81526001600160a01b0386811660048301525f919085169063c37f68e290602401608060405180830381865afa1580156102f0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103149190610fbc565b60c086015260408501526020840152905080156103695760405162461bcd60e51b815260206004820152600e60248201526d29b730b839b437ba1022b93937b960911b60448201526064015b60405180910390fd5b6040805160208101825260c08401518152610120840152516319ef3e8b60e01b81525f906001600160a01b038716906319ef3e8b906103b0908a9089908690600401610fef565b602060405180830381865afa1580156103cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ef9190611031565b9050604051806020016040528082815250836101000181905250856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610445573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104699190611048565b60405163fc57d4df60e01b81526001600160a01b038781166004830152919091169063fc57d4df90602401602060405180830381865afa1580156104af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104d39190611031565b60e0840190815260408051602081019091529051815261014084015261010083015161012084015161051391610508916109db565b8461014001516109db565b6101608401819052602084015161052a9190610a20565b8352604051633af9e66960e01b81526001600160a01b038881166004830152861690633af9e669906024016020604051808303815f875af1158015610571573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105959190611031565b608084018190526101408401516105ab91610a20565b60a084015261014083015160408401516105c59190610a20565b8360600181815250505f80610657876001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa15801561060e573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106359190810190611063565b604051806040016040528060048152602001633b21272160e11b815250610a3f565b1561066757505f90506012610793565b5f879050806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106cb9190611048565b9250806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610709573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072d9190611048565b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610768573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061078c91906110f2565b60ff169150505b61079e89888a6101cc565b85610180019015159081151581525050604051806101e001604052808a6001600160a01b03168152602001886001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa158015610804573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261082b9190810190611063565b8152602001886001600160a01b03168152602001836001600160a01b03168152602001866080015181526020018660a001518152602001865f0151815260200186604001518152602001866060015181526020018660e001518152602001886001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e99190611031565b8152602001886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561092a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061094e91906110f2565b60ff168152602001828152602001886001600160a01b031663bd6d894d6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610999573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109bd9190611031565b81526020018661018001511515815250955050505050509392505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610a0d865f0151865f0151610a97565b610a179190611112565b90529392505050565b5f80610a2c8484610ad8565b9050610a3781610afe565b949350505050565b5f81604051602001610a519190611131565b6040516020818303038152906040528051906020012083604051602001610a789190611131565b6040516020818303038152906040528051906020012014905092915050565b5f61029283836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250610b15565b60408051602081019091525f81526040518060200160405280610a17855f015185610a97565b80515f906101c690670de0b6b3a764000090611112565b5f831580610b21575082155b15610b2d57505f610292565b5f610b388486611147565b905083610b458683611112565b148390610b655760405162461bcd60e51b8152600401610360919061116a565b50949350505050565b604051806101e001604052805f6001600160a01b03168152602001606081526020015f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f151581525090565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001610c4460405180602001604052805f81525090565b8152602001610c5e60405180602001604052805f81525090565b8152602001610c7860405180602001604052805f81525090565b8152602001610c9260405180602001604052805f81525090565b81525f60209091015290565b6001600160a01b0381168114610cb2575f80fd5b50565b5f8060408385031215610cc6575f80fd5b8235610cd181610c9e565b91506020830135610ce181610c9e565b809150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b80516001600160a01b031682525f6101e06020830151816020860152610d4282860182610cec565b9150506040830151610d5f60408601826001600160a01b03169052565b506060830151610d7a60608601826001600160a01b03169052565b506080838101519085015260a0808401519085015260c0808401519085015260e08084015190850152610100808401519085015261012080840151908501526101408084015190850152610160808401519085015261018080840151908501526101a080840151908501526101c092830151151592909301919091525090565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015610e4f57603f19888603018452610e3d858351610d1a565b94509285019290850190600101610e21565b5092979650505050505050565b5f805f60608486031215610e6e575f80fd5b8335610e7981610c9e565b92506020840135610e8981610c9e565b91506040840135610e9981610c9e565b809150509250925092565b602081525f6102926020830184610d1a565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610ef357610ef3610eb6565b604052919050565b5f6020808385031215610f0c575f80fd5b825167ffffffffffffffff80821115610f23575f80fd5b818501915085601f830112610f36575f80fd5b815181811115610f4857610f48610eb6565b8060051b9150610f59848301610eca565b8181529183018401918481019088841115610f72575f80fd5b938501935b83851015610f9c5784519250610f8c83610c9e565b8282529385019390850190610f77565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215610fcf575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061102357634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f60208284031215611041575f80fd5b5051919050565b5f60208284031215611058575f80fd5b815161029281610c9e565b5f6020808385031215611074575f80fd5b825167ffffffffffffffff8082111561108b575f80fd5b818501915085601f83011261109e575f80fd5b8151818111156110b0576110b0610eb6565b6110c2601f8201601f19168501610eca565b915080825286848285010111156110d7575f80fd5b808484018584015e5f90820190930192909252509392505050565b5f60208284031215611102575f80fd5b815160ff81168114610292575f80fd5b5f8261112c57634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f920191825250919050565b80820281158282048414176101c657634e487b7160e01b5f52601160045260245ffd5b602081525f6102926020830184610cec56fea26469706673582212205d456933e9038113441a382bbe25bba29b2f3d583db0e97a6d92f232bdd5ebf264736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061003f575f3560e01c806332221cf614610043578063e6bf1d3a1461006c578063ebdf591a1461008f575b5f80fd5b610056610051366004610cb5565b6100af565b6040516100639190610dfa565b60405180910390f35b61007f61007a366004610e5c565b6101cc565b6040519015158152602001610063565b6100a261009d366004610e5c565b610299565b6040516100639190610ea4565b60605f826001600160a01b031663b0772d0b6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156100ed573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526101149190810190610efb565b90505f815167ffffffffffffffff81111561013157610131610eb6565b60405190808252806020026020018201604052801561016a57816020015b610157610b6e565b81526020019060019003908161014f5790505b5090505f5b82518110156101c15761019c868685848151811061018f5761018f610fa8565b6020026020010151610299565b8282815181106101ae576101ae610fa8565b602090810291909101015260010161016f565b509150505b92915050565b604051632aff3bff60e21b81526001600160a01b0384811660048301525f91829184169063abfceffc906024015f60405180830381865afa158015610213573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261023a9190810190610efb565b90505f5b815181101561028c57846001600160a01b031682828151811061026357610263610fa8565b60200260200101516001600160a01b03160361028457600192505050610292565b60010161023e565b505f9150505b9392505050565b6102a1610b6e565b6102a9610bf3565b6040516361bfb47160e11b81526001600160a01b0386811660048301525f919085169063c37f68e290602401608060405180830381865afa1580156102f0573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103149190610fbc565b60c086015260408501526020840152905080156103695760405162461bcd60e51b815260206004820152600e60248201526d29b730b839b437ba1022b93937b960911b60448201526064015b60405180910390fd5b6040805160208101825260c08401518152610120840152516319ef3e8b60e01b81525f906001600160a01b038716906319ef3e8b906103b0908a9089908690600401610fef565b602060405180830381865afa1580156103cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ef9190611031565b9050604051806020016040528082815250836101000181905250856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610445573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104699190611048565b60405163fc57d4df60e01b81526001600160a01b038781166004830152919091169063fc57d4df90602401602060405180830381865afa1580156104af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104d39190611031565b60e0840190815260408051602081019091529051815261014084015261010083015161012084015161051391610508916109db565b8461014001516109db565b6101608401819052602084015161052a9190610a20565b8352604051633af9e66960e01b81526001600160a01b038881166004830152861690633af9e669906024016020604051808303815f875af1158015610571573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105959190611031565b608084018190526101408401516105ab91610a20565b60a084015261014083015160408401516105c59190610a20565b8360600181815250505f80610657876001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa15801561060e573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106359190810190611063565b604051806040016040528060048152602001633b21272160e11b815250610a3f565b1561066757505f90506012610793565b5f879050806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156106a7573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106cb9190611048565b9250806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa158015610709573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061072d9190611048565b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610768573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061078c91906110f2565b60ff169150505b61079e89888a6101cc565b85610180019015159081151581525050604051806101e001604052808a6001600160a01b03168152602001886001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa158015610804573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261082b9190810190611063565b8152602001886001600160a01b03168152602001836001600160a01b03168152602001866080015181526020018660a001518152602001865f0151815260200186604001518152602001866060015181526020018660e001518152602001886001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108e99190611031565b8152602001886001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561092a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061094e91906110f2565b60ff168152602001828152602001886001600160a01b031663bd6d894d6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610999573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109bd9190611031565b81526020018661018001511515815250955050505050509392505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610a0d865f0151865f0151610a97565b610a179190611112565b90529392505050565b5f80610a2c8484610ad8565b9050610a3781610afe565b949350505050565b5f81604051602001610a519190611131565b6040516020818303038152906040528051906020012083604051602001610a789190611131565b6040516020818303038152906040528051906020012014905092915050565b5f61029283836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250610b15565b60408051602081019091525f81526040518060200160405280610a17855f015185610a97565b80515f906101c690670de0b6b3a764000090611112565b5f831580610b21575082155b15610b2d57505f610292565b5f610b388486611147565b905083610b458683611112565b148390610b655760405162461bcd60e51b8152600401610360919061116a565b50949350505050565b604051806101e001604052805f6001600160a01b03168152602001606081526020015f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f151581525090565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001610c4460405180602001604052805f81525090565b8152602001610c5e60405180602001604052805f81525090565b8152602001610c7860405180602001604052805f81525090565b8152602001610c9260405180602001604052805f81525090565b81525f60209091015290565b6001600160a01b0381168114610cb2575f80fd5b50565b5f8060408385031215610cc6575f80fd5b8235610cd181610c9e565b91506020830135610ce181610c9e565b809150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b80516001600160a01b031682525f6101e06020830151816020860152610d4282860182610cec565b9150506040830151610d5f60408601826001600160a01b03169052565b506060830151610d7a60608601826001600160a01b03169052565b506080838101519085015260a0808401519085015260c0808401519085015260e08084015190850152610100808401519085015261012080840151908501526101408084015190850152610160808401519085015261018080840151908501526101a080840151908501526101c092830151151592909301919091525090565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015610e4f57603f19888603018452610e3d858351610d1a565b94509285019290850190600101610e21565b5092979650505050505050565b5f805f60608486031215610e6e575f80fd5b8335610e7981610c9e565b92506020840135610e8981610c9e565b91506040840135610e9981610c9e565b809150509250925092565b602081525f6102926020830184610d1a565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610ef357610ef3610eb6565b604052919050565b5f6020808385031215610f0c575f80fd5b825167ffffffffffffffff80821115610f23575f80fd5b818501915085601f830112610f36575f80fd5b815181811115610f4857610f48610eb6565b8060051b9150610f59848301610eca565b8181529183018401918481019088841115610f72575f80fd5b938501935b83851015610f9c5784519250610f8c83610c9e565b8282529385019390850190610f77565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215610fcf575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061102357634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f60208284031215611041575f80fd5b5051919050565b5f60208284031215611058575f80fd5b815161029281610c9e565b5f6020808385031215611074575f80fd5b825167ffffffffffffffff8082111561108b575f80fd5b818501915085601f83011261109e575f80fd5b8151818111156110b0576110b0610eb6565b6110c2601f8201601f19168501610eca565b915080825286848285010111156110d7575f80fd5b808484018584015e5f90820190930192909252509392505050565b5f60208284031215611102575f80fd5b815160ff81168114610292575f80fd5b5f8261112c57634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f920191825250919050565b80820281158282048414176101c657634e487b7160e01b5f52601160045260245ffd5b602081525f6102926020830184610cec56fea26469706673582212205d456933e9038113441a382bbe25bba29b2f3d583db0e97a6d92f232bdd5ebf264736f6c63430008190033", + "numDeployments": 4, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"getAccountSnapshot\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"assetName\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowsInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"spotPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"boundedCollateralPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"boundedDebtPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"accruedInterest\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isACollateral\",\"type\":\"bool\"}],\"internalType\":\"struct SnapshotLens.AccountSnapshot[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"},{\"internalType\":\"contract VToken\",\"name\":\"vToken\",\"type\":\"address\"}],\"name\":\"getAccountSnapshot\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"string\",\"name\":\"assetName\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"vTokenAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"underlyingAssetAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"supply\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"supplyInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrows\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"borrowsInUsd\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"spotPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"boundedCollateralPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"boundedDebtPrice\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"accruedInterest\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"vTokenDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"underlyingDecimals\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"exchangeRate\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isACollateral\",\"type\":\"bool\"}],\"internalType\":\"struct SnapshotLens.AccountSnapshot\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"asset\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"comptrollerAddress\",\"type\":\"address\"}],\"name\":\"isACollateral\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Lens/SnapshotLens.sol\":\"SnapshotLens\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev 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 amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\\n}\\n\",\"keccak256\":\"0x287b55befed2961a7eabd7d7b1b2839cbca8a5b80ef8dcbb25ed3d4c2002c305\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\n\\n/**\\n * @dev Interface for the optional metadata functions from the ERC20 standard.\\n *\\n * _Available since v4.1._\\n */\\ninterface IERC20Metadata is IERC20 {\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() external view returns (string memory);\\n\\n /**\\n * @dev Returns the symbol of the token.\\n */\\n function symbol() external view returns (string memory);\\n\\n /**\\n * @dev Returns the decimals places of the token.\\n */\\n function decimals() external view returns (uint8);\\n}\\n\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xec63854014a5b4f2b3290ab9103a21bdf902a508d0f41a8573fea49e98bf571a\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n /**\\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\\n }\\n\\n /**\\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\\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.encodeWithSelector(token.approve.selector, spender, value);\\n\\n if (!_callOptionalReturnBool(token, approvalCall)) {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\\n _callOptionalReturn(token, approvalCall);\\n }\\n }\\n\\n /**\\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\\n * Revert on invalid signature.\\n */\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\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\\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\\n }\\n}\\n\",\"keccak256\":\"0xabefac93435967b4d36a4fabcbdbb918d1f0b7ae3c3d85bc30923b326c927ed1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n *\\n * Furthermore, `isContract` will also return true if the target contract within\\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\\n * which only has an effect at the end of a transaction.\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0x006dd67219697fe68d7fbfdea512e7c4cb64a43565ed86171d67e844982da6fa\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Lens/SnapshotLens.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20Metadata } from \\\"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { ExponentialNoError } from \\\"../Utils/ExponentialNoError.sol\\\";\\nimport { ComptrollerInterface } from \\\"../Comptroller/ComptrollerInterface.sol\\\";\\nimport { VBep20 } from \\\"../Tokens/VTokens/VBep20.sol\\\";\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\ncontract SnapshotLens is ExponentialNoError {\\n struct AccountSnapshot {\\n address account;\\n string assetName;\\n address vTokenAddress;\\n address underlyingAssetAddress;\\n uint256 supply;\\n uint256 supplyInUsd;\\n uint256 collateral;\\n uint256 borrows;\\n uint256 borrowsInUsd;\\n uint256 spotPrice;\\n uint256 boundedCollateralPrice;\\n uint256 boundedDebtPrice;\\n uint256 accruedInterest;\\n uint vTokenDecimals;\\n uint underlyingDecimals;\\n uint exchangeRate;\\n bool isACollateral;\\n }\\n\\n /** Snapshot calculation **/\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account snapshot.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountSnapshotLocalVars {\\n uint collateral;\\n uint vTokenBalance;\\n uint borrowBalance;\\n uint borrowsInUsd;\\n uint balanceOfUnderlying;\\n uint supplyInUsd;\\n uint exchangeRateMantissa;\\n uint oraclePriceMantissa;\\n Exp collateralFactor;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n bool isACollateral;\\n }\\n\\n function getAccountSnapshot(\\n address payable account,\\n address comptrollerAddress\\n ) public returns (AccountSnapshot[] memory) {\\n // For each asset the account is in\\n VToken[] memory assets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\\n AccountSnapshot[] memory accountSnapshots = new AccountSnapshot[](assets.length);\\n for (uint256 i = 0; i < assets.length; ++i) {\\n accountSnapshots[i] = getAccountSnapshot(account, comptrollerAddress, assets[i]);\\n }\\n return accountSnapshots;\\n }\\n\\n function isACollateral(address account, address asset, address comptrollerAddress) public view returns (bool) {\\n VToken[] memory assetsAsCollateral = ComptrollerInterface(comptrollerAddress).getAssetsIn(account);\\n for (uint256 j = 0; j < assetsAsCollateral.length; ++j) {\\n if (address(assetsAsCollateral[j]) == asset) {\\n return true;\\n }\\n }\\n\\n return false;\\n }\\n\\n function getAccountSnapshot(\\n address payable account,\\n address comptrollerAddress,\\n VToken vToken\\n ) public returns (AccountSnapshot memory) {\\n AccountSnapshotLocalVars memory vars; // Holds all our calculation results\\n uint oErr;\\n\\n // Read the balances and exchange rate from the vToken\\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = vToken.getAccountSnapshot(account);\\n require(oErr == 0, \\\"Snapshot Error\\\");\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n uint collateralFactorMantissa = ComptrollerInterface(comptrollerAddress).getEffectiveLtvFactor(\\n account,\\n address(vToken),\\n WeightFunction.USE_COLLATERAL_FACTOR\\n );\\n vars.collateralFactor = Exp({ mantissa: collateralFactorMantissa });\\n\\n // Get the normalized spot price of the asset\\n vars.oraclePriceMantissa = ComptrollerInterface(comptrollerAddress).oracle().getUnderlyingPrice(\\n address(vToken)\\n );\\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n\\n // Get bounded prices from DBO (used in CF-path liquidity calculations)\\n IDeviationBoundedOracle boundedOracle = ComptrollerInterface(comptrollerAddress).deviationBoundedOracle();\\n (uint256 boundedCollateralPriceMantissa, uint256 boundedDebtPriceMantissa) = boundedOracle.getBoundedPricesView(\\n address(vToken)\\n );\\n\\n // Collateral uses bounded collateral price (mirrors ComptrollerLens CF path)\\n Exp memory collateralPrice = Exp({ mantissa: boundedCollateralPriceMantissa });\\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), collateralPrice);\\n vars.collateral = mul_ScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\\n\\n // Supply in USD uses spot price (real market value of supplied assets)\\n vars.balanceOfUnderlying = vToken.balanceOfUnderlying(account);\\n vars.supplyInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.balanceOfUnderlying);\\n\\n // Borrows in USD uses bounded debt price (mirrors ComptrollerLens CF path)\\n Exp memory debtPrice = Exp({ mantissa: boundedDebtPriceMantissa });\\n vars.borrowsInUsd = mul_ScalarTruncate(debtPrice, vars.borrowBalance);\\n\\n address underlyingAssetAddress;\\n uint underlyingDecimals;\\n\\n if (compareStrings(vToken.symbol(), \\\"vBNB\\\")) {\\n underlyingAssetAddress = address(0);\\n underlyingDecimals = 18;\\n } else {\\n VBep20 vBep20 = VBep20(address(vToken));\\n underlyingAssetAddress = vBep20.underlying();\\n underlyingDecimals = IERC20Metadata(vBep20.underlying()).decimals();\\n }\\n\\n vars.isACollateral = isACollateral(account, address(vToken), comptrollerAddress);\\n\\n return\\n AccountSnapshot({\\n account: account,\\n assetName: vToken.name(),\\n vTokenAddress: address(vToken),\\n underlyingAssetAddress: underlyingAssetAddress,\\n supply: vars.balanceOfUnderlying,\\n supplyInUsd: vars.supplyInUsd,\\n collateral: vars.collateral,\\n borrows: vars.borrowBalance,\\n borrowsInUsd: vars.borrowsInUsd,\\n spotPrice: vars.oraclePriceMantissa,\\n boundedCollateralPrice: boundedCollateralPriceMantissa,\\n boundedDebtPrice: boundedDebtPriceMantissa,\\n accruedInterest: vToken.borrowIndex(),\\n vTokenDecimals: vToken.decimals(),\\n underlyingDecimals: underlyingDecimals,\\n exchangeRate: vToken.exchangeRateCurrent(),\\n isACollateral: vars.isACollateral\\n });\\n }\\n\\n // utilities\\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\\n }\\n}\\n\",\"keccak256\":\"0x00dab074f7000cafb7d97787e7eb7d41747d1ea3185e2254285268aed2185b8f\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VBep20.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IERC20 } from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport { SafeERC20 } from \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VBep20Interface, VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { VToken } from \\\"./VToken.sol\\\";\\n\\n/**\\n * @title Venus's VBep20 Contract\\n * @notice vTokens which wrap an ERC-20 underlying\\n * @author Venus\\n */\\ncontract VBep20 is VToken, VBep20Interface {\\n using SafeERC20 for IERC20;\\n\\n /*** User Interface ***/\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n // @custom:event Emits Mint event\\n function mint(uint mintAmount) external returns (uint) {\\n (uint err, ) = mintInternal(mintAmount);\\n return err;\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n // @custom:event Emits MintBehalf event\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\\n (uint err, ) = mintBehalfInternal(receiver, mintAmount);\\n return err;\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for the underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Redeem event on success\\n // @custom:event Emits Transfer event on success\\n // @custom:event Emits RedeemFee when fee is charged by the treasury\\n function redeem(uint redeemTokens) external returns (uint) {\\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\\n }\\n\\n /**\\n * @notice Sender redeems assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The user on behalf of whom to redeem\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Redeem event on success\\n // @custom:event Emits Transfer event on success\\n // @custom:event Emits RedeemFee when fee is charged by the treasury\\n function redeemBehalf(address redeemer, uint redeemTokens) external returns (uint) {\\n require(comptroller.approvedDelegates(redeemer, msg.sender), \\\"not an approved delegate\\\");\\n\\n return redeemInternal(redeemer, payable(msg.sender), redeemTokens);\\n }\\n\\n /**\\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemAmount The amount of underlying to redeem\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Redeem event on success\\n // @custom:event Emits Transfer event on success\\n // @custom:event Emits RedeemFee when fee is charged by the treasury\\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer, on behalf of whom to redeem\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Redeem event on success\\n // @custom:event Emits Transfer event on success\\n // @custom:event Emits RedeemFee when fee is charged by the treasury\\n function redeemUnderlyingBehalf(address redeemer, uint redeemAmount) external returns (uint) {\\n require(comptroller.approvedDelegates(redeemer, msg.sender), \\\"not an approved delegate\\\");\\n\\n return redeemUnderlyingInternal(redeemer, payable(msg.sender), redeemAmount);\\n }\\n\\n /**\\n * @notice Sender borrows assets from the protocol to their own address\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Borrow event on success\\n function borrow(uint borrowAmount) external returns (uint) {\\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\\n }\\n\\n /**\\n * @notice Sender borrows assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the borrower using `comptroller.updateDelegate`\\n * @param borrower The borrower, on behalf of whom to borrow.\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Borrow event on success\\n function borrowBehalf(address borrower, uint borrowAmount) external returns (uint) {\\n require(comptroller.approvedDelegates(borrower, msg.sender), \\\"not an approved delegate\\\");\\n return borrowInternal(borrower, payable(msg.sender), borrowAmount);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits RepayBorrow event on success\\n function repayBorrow(uint repayAmount) external returns (uint) {\\n (uint err, ) = repayBorrowInternal(repayAmount);\\n return err;\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits RepayBorrow event on success\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\\n (uint err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\\n return err;\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emit LiquidateBorrow event on success\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint) {\\n (uint err, ) = liquidateBorrowInternal(borrower, repayAmount, vTokenCollateral);\\n return err;\\n }\\n\\n /**\\n * @notice The sender adds to reserves.\\n * @param addAmount The amount of underlying tokens to add as reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesAdded event\\n function _addReserves(uint addAmount) external returns (uint) {\\n return _addReservesInternal(addAmount);\\n }\\n\\n /**\\n * @notice Initialize the new money market\\n * @param underlying_ The address of the underlying asset\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ BEP-20 name of this token\\n * @param symbol_ BEP-20 symbol of this token\\n * @param decimals_ BEP-20 decimal precision of this token\\n */\\n function initialize(\\n address underlying_,\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n // VToken initialize does the bulk of the work\\n super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\\n\\n // Set underlying and sanity check it\\n underlying = underlying_;\\n IERC20(underlying).totalSupply();\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\\n * This function returns the actual amount received,\\n * which may be less than `amount` if there is a fee attached to the transfer.\\n * Increments `internalCash` by the actual amount received.\\n * @param from Sender of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n * @return Actual amount received\\n */\\n function doTransferIn(address from, uint256 amount) internal virtual override returns (uint256) {\\n IERC20 token = IERC20(underlying);\\n uint256 balanceBefore = token.balanceOf(address(this));\\n token.safeTransferFrom(from, address(this), amount);\\n uint256 balanceAfter = token.balanceOf(address(this));\\n uint256 actualAmount = balanceAfter - balanceBefore;\\n internalCash += actualAmount;\\n // Return the amount that was *actually* transferred\\n return actualAmount;\\n }\\n\\n /**\\n * @dev Just a regular ERC-20 transfer, reverts on failure.\\n * Decrements `internalCash` by `amount` before transferring.\\n * @param to Receiver of the underlying tokens\\n * @param amount Amount of underlying to transfer\\n */\\n function doTransferOut(address payable to, uint256 amount) internal virtual override {\\n internalCash -= amount;\\n IERC20 token = IERC20(underlying);\\n token.safeTransfer(to, amount);\\n }\\n\\n /**\\n * @notice Gets the tracked internal cash balance of this contract\\n * @dev Returns `internalCash` rather than the actual token balance, making it immune to donation attacks.\\n * @return The internally tracked cash balance of underlying tokens\\n */\\n function getCashPrior() internal view override returns (uint) {\\n return internalCash;\\n }\\n\\n /**\\n * @notice Transfer excess tokens to caller and sync internalCash with actual balance\\n * @dev Admin-only. For migration: pass 0 (just syncs). For sweep: pass the excess amount.\\n * Transfers `transferAmount` of underlying to msg.sender, then sets internalCash = balanceOf(address(this)).\\n * @param transferAmount Amount of underlying to transfer to msg.sender before syncing\\n */\\n function sweepTokenAndSync(uint256 transferAmount) external {\\n require(msg.sender == admin);\\n\\n if (transferAmount > 0) {\\n IERC20(underlying).safeTransfer(msg.sender, transferAmount);\\n emit TokenSwept(msg.sender, transferAmount);\\n }\\n\\n uint256 oldInternalCash = internalCash;\\n internalCash = IERC20(underlying).balanceOf(address(this));\\n emit CashSynced(oldInternalCash, internalCash);\\n }\\n}\\n\",\"keccak256\":\"0xe0fb090201a3eb693d35d6ffeef4a00bd2d6a6109e22eed529345a6aba13feb3\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b506112ef8061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061003f575f3560e01c806332221cf614610043578063e6bf1d3a1461006c578063ebdf591a1461008f575b5f80fd5b610056610051366004610dba565b6100af565b6040516100639190610f15565b60405180910390f35b61007f61007a366004610f77565b6101cc565b6040519015158152602001610063565b6100a261009d366004610f77565b610299565b6040516100639190610fbf565b60605f826001600160a01b031663b0772d0b6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156100ed573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526101149190810190611016565b90505f815167ffffffffffffffff81111561013157610131610fd1565b60405190808252806020026020018201604052801561016a57816020015b610157610c67565b81526020019060019003908161014f5790505b5090505f5b82518110156101c15761019c868685848151811061018f5761018f6110c3565b6020026020010151610299565b8282815181106101ae576101ae6110c3565b602090810291909101015260010161016f565b509150505b92915050565b604051632aff3bff60e21b81526001600160a01b0384811660048301525f91829184169063abfceffc906024015f60405180830381865afa158015610213573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261023a9190810190611016565b90505f5b815181101561028c57846001600160a01b0316828281518110610263576102636110c3565b60200260200101516001600160a01b03160361028457600192505050610292565b60010161023e565b505f9150505b9392505050565b6102a1610c67565b6102a9610cf8565b6040516361bfb47160e11b81526001600160a01b0386811660048301525f919085169063c37f68e290602401608060405180830381865afa1580156102f0573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031491906110d7565b60c086015260408501526020840152905080156103695760405162461bcd60e51b815260206004820152600e60248201526d29b730b839b437ba1022b93937b960911b60448201526064015b60405180910390fd5b6040805160208101825260c08401518152610120840152516319ef3e8b60e01b81525f906001600160a01b038716906319ef3e8b906103b0908a908990869060040161110a565b602060405180830381865afa1580156103cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ef919061114c565b9050604051806020016040528082815250836101000181905250856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610445573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104699190611163565b60405163fc57d4df60e01b81526001600160a01b038781166004830152919091169063fc57d4df90602401602060405180830381865afa1580156104af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104d3919061114c565b60e08401908152604080516020808201835292518152610140860152805163d7c46d2d60e01b815290515f926001600160a01b038a169263d7c46d2d92600480830193928290030181865afa15801561052e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105529190611163565b6040516388142b6b60e01b81526001600160a01b0388811660048301529192505f918291908416906388142b6b906024016040805180830381865afa15801561059d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c1919061117e565b915091505f60405180602001604052808481525090506105f46105ee886101000151896101200151610ad4565b82610ad4565b6101608801819052602088015161060b9190610b19565b8752604051633af9e66960e01b81526001600160a01b038c811660048301528a1690633af9e669906024016020604051808303815f875af1158015610652573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610676919061114c565b6080880181905261014088015161068c91610b19565b60a088015260408051602081018252838152908801516106ad908290610b19565b8860600181815250505f8061073f8c6001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa1580156106f6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261071d91908101906111a0565b604051806040016040528060048152602001633b21272160e11b815250610b38565b1561074f57505f9050601261087b565b5f8c9050806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561078f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107b39190611163565b9250806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107f1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108159190611163565b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610850573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610874919061122f565b60ff169150505b6108868e8d8f6101cc565b8a6101800190151590811515815250506040518061022001604052808f6001600160a01b031681526020018d6001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa1580156108ec573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261091391908101906111a0565b81526020018d6001600160a01b03168152602001836001600160a01b031681526020018b6080015181526020018b60a0015181526020018b5f015181526020018b6040015181526020018b6060015181526020018b60e0015181526020018781526020018681526020018d6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109dd919061114c565b81526020018d6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a42919061122f565b60ff1681526020018281526020018d6001600160a01b031663bd6d894d6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab1919061114c565b81526020018b610180015115158152509a50505050505050505050509392505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610b06865f0151865f0151610b90565b610b10919061124f565b90529392505050565b5f80610b258484610bd1565b9050610b3081610bf7565b949350505050565b5f81604051602001610b4a919061126e565b6040516020818303038152906040528051906020012083604051602001610b71919061126e565b6040516020818303038152906040528051906020012014905092915050565b5f61029283836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250610c0e565b60408051602081019091525f81526040518060200160405280610b10855f015185610b90565b80515f906101c690670de0b6b3a76400009061124f565b5f831580610c1a575082155b15610c2657505f610292565b5f610c318486611284565b905083610c3e868361124f565b148390610c5e5760405162461bcd60e51b815260040161036091906112a7565b50949350505050565b6040518061022001604052805f6001600160a01b03168152602001606081526020015f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f151581525090565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001610d4960405180602001604052805f81525090565b8152602001610d6360405180602001604052805f81525090565b8152602001610d7d60405180602001604052805f81525090565b8152602001610d9760405180602001604052805f81525090565b81525f60209091015290565b6001600160a01b0381168114610db7575f80fd5b50565b5f8060408385031215610dcb575f80fd5b8235610dd681610da3565b91506020830135610de681610da3565b809150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b80516001600160a01b031682525f6102206020830151816020860152610e4782860182610df1565b9150506040830151610e6460408601826001600160a01b03169052565b506060830151610e7f60608601826001600160a01b03169052565b506080838101519085015260a0808401519085015260c0808401519085015260e08084015190850152610100808401519085015261012080840151908501526101408084015190850152610160808401519085015261018080840151908501526101a080840151908501526101c080840151908501526101e0808401519085015261020092830151151592909301919091525090565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015610f6a57603f19888603018452610f58858351610e1f565b94509285019290850190600101610f3c565b5092979650505050505050565b5f805f60608486031215610f89575f80fd5b8335610f9481610da3565b92506020840135610fa481610da3565b91506040840135610fb481610da3565b809150509250925092565b602081525f6102926020830184610e1f565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561100e5761100e610fd1565b604052919050565b5f6020808385031215611027575f80fd5b825167ffffffffffffffff8082111561103e575f80fd5b818501915085601f830112611051575f80fd5b81518181111561106357611063610fd1565b8060051b9150611074848301610fe5565b818152918301840191848101908884111561108d575f80fd5b938501935b838510156110b757845192506110a783610da3565b8282529385019390850190611092565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f80608085870312156110ea575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061113e57634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f6020828403121561115c575f80fd5b5051919050565b5f60208284031215611173575f80fd5b815161029281610da3565b5f806040838503121561118f575f80fd5b505080516020909101519092909150565b5f60208083850312156111b1575f80fd5b825167ffffffffffffffff808211156111c8575f80fd5b818501915085601f8301126111db575f80fd5b8151818111156111ed576111ed610fd1565b6111ff601f8201601f19168501610fe5565b91508082528684828501011115611214575f80fd5b808484018584015e5f90820190930192909252509392505050565b5f6020828403121561123f575f80fd5b815160ff81168114610292575f80fd5b5f8261126957634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f920191825250919050565b80820281158282048414176101c657634e487b7160e01b5f52601160045260245ffd5b602081525f6102926020830184610df156fea2646970667358221220061cabf537e7b384ce2bf50908912924989afd923ae63da282423eafd6f69aff64736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061003f575f3560e01c806332221cf614610043578063e6bf1d3a1461006c578063ebdf591a1461008f575b5f80fd5b610056610051366004610dba565b6100af565b6040516100639190610f15565b60405180910390f35b61007f61007a366004610f77565b6101cc565b6040519015158152602001610063565b6100a261009d366004610f77565b610299565b6040516100639190610fbf565b60605f826001600160a01b031663b0772d0b6040518163ffffffff1660e01b81526004015f60405180830381865afa1580156100ed573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526101149190810190611016565b90505f815167ffffffffffffffff81111561013157610131610fd1565b60405190808252806020026020018201604052801561016a57816020015b610157610c67565b81526020019060019003908161014f5790505b5090505f5b82518110156101c15761019c868685848151811061018f5761018f6110c3565b6020026020010151610299565b8282815181106101ae576101ae6110c3565b602090810291909101015260010161016f565b509150505b92915050565b604051632aff3bff60e21b81526001600160a01b0384811660048301525f91829184169063abfceffc906024015f60405180830381865afa158015610213573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261023a9190810190611016565b90505f5b815181101561028c57846001600160a01b0316828281518110610263576102636110c3565b60200260200101516001600160a01b03160361028457600192505050610292565b60010161023e565b505f9150505b9392505050565b6102a1610c67565b6102a9610cf8565b6040516361bfb47160e11b81526001600160a01b0386811660048301525f919085169063c37f68e290602401608060405180830381865afa1580156102f0573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061031491906110d7565b60c086015260408501526020840152905080156103695760405162461bcd60e51b815260206004820152600e60248201526d29b730b839b437ba1022b93937b960911b60448201526064015b60405180910390fd5b6040805160208101825260c08401518152610120840152516319ef3e8b60e01b81525f906001600160a01b038716906319ef3e8b906103b0908a908990869060040161110a565b602060405180830381865afa1580156103cb573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906103ef919061114c565b9050604051806020016040528082815250836101000181905250856001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610445573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104699190611163565b60405163fc57d4df60e01b81526001600160a01b038781166004830152919091169063fc57d4df90602401602060405180830381865afa1580156104af573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906104d3919061114c565b60e08401908152604080516020808201835292518152610140860152805163d7c46d2d60e01b815290515f926001600160a01b038a169263d7c46d2d92600480830193928290030181865afa15801561052e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105529190611163565b6040516388142b6b60e01b81526001600160a01b0388811660048301529192505f918291908416906388142b6b906024016040805180830381865afa15801561059d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105c1919061117e565b915091505f60405180602001604052808481525090506105f46105ee886101000151896101200151610ad4565b82610ad4565b6101608801819052602088015161060b9190610b19565b8752604051633af9e66960e01b81526001600160a01b038c811660048301528a1690633af9e669906024016020604051808303815f875af1158015610652573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610676919061114c565b6080880181905261014088015161068c91610b19565b60a088015260408051602081018252838152908801516106ad908290610b19565b8860600181815250505f8061073f8c6001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa1580156106f6573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261071d91908101906111a0565b604051806040016040528060048152602001633b21272160e11b815250610b38565b1561074f57505f9050601261087b565b5f8c9050806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561078f573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906107b39190611163565b9250806001600160a01b0316636f307dc36040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107f1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108159190611163565b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610850573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610874919061122f565b60ff169150505b6108868e8d8f6101cc565b8a6101800190151590811515815250506040518061022001604052808f6001600160a01b031681526020018d6001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa1580156108ec573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261091391908101906111a0565b81526020018d6001600160a01b03168152602001836001600160a01b031681526020018b6080015181526020018b60a0015181526020018b5f015181526020018b6040015181526020018b6060015181526020018b60e0015181526020018781526020018681526020018d6001600160a01b031663aa5af0fd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109b9573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109dd919061114c565b81526020018d6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a1e573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a42919061122f565b60ff1681526020018281526020018d6001600160a01b031663bd6d894d6040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a8d573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ab1919061114c565b81526020018b610180015115158152509a50505050505050505050509392505050565b60408051602081019091525f81526040518060200160405280670de0b6b3a7640000610b06865f0151865f0151610b90565b610b10919061124f565b90529392505050565b5f80610b258484610bd1565b9050610b3081610bf7565b949350505050565b5f81604051602001610b4a919061126e565b6040516020818303038152906040528051906020012083604051602001610b71919061126e565b6040516020818303038152906040528051906020012014905092915050565b5f61029283836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250610c0e565b60408051602081019091525f81526040518060200160405280610b10855f015185610b90565b80515f906101c690670de0b6b3a76400009061124f565b5f831580610c1a575082155b15610c2657505f610292565b5f610c318486611284565b905083610c3e868361124f565b148390610c5e5760405162461bcd60e51b815260040161036091906112a7565b50949350505050565b6040518061022001604052805f6001600160a01b03168152602001606081526020015f6001600160a01b031681526020015f6001600160a01b031681526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f151581525090565b604051806101a001604052805f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001610d4960405180602001604052805f81525090565b8152602001610d6360405180602001604052805f81525090565b8152602001610d7d60405180602001604052805f81525090565b8152602001610d9760405180602001604052805f81525090565b81525f60209091015290565b6001600160a01b0381168114610db7575f80fd5b50565b5f8060408385031215610dcb575f80fd5b8235610dd681610da3565b91506020830135610de681610da3565b809150509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b80516001600160a01b031682525f6102206020830151816020860152610e4782860182610df1565b9150506040830151610e6460408601826001600160a01b03169052565b506060830151610e7f60608601826001600160a01b03169052565b506080838101519085015260a0808401519085015260c0808401519085015260e08084015190850152610100808401519085015261012080840151908501526101408084015190850152610160808401519085015261018080840151908501526101a080840151908501526101c080840151908501526101e0808401519085015261020092830151151592909301919091525090565b5f60208083016020845280855180835260408601915060408160051b8701019250602087015f5b82811015610f6a57603f19888603018452610f58858351610e1f565b94509285019290850190600101610f3c565b5092979650505050505050565b5f805f60608486031215610f89575f80fd5b8335610f9481610da3565b92506020840135610fa481610da3565b91506040840135610fb481610da3565b809150509250925092565b602081525f6102926020830184610e1f565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f1916810167ffffffffffffffff8111828210171561100e5761100e610fd1565b604052919050565b5f6020808385031215611027575f80fd5b825167ffffffffffffffff8082111561103e575f80fd5b818501915085601f830112611051575f80fd5b81518181111561106357611063610fd1565b8060051b9150611074848301610fe5565b818152918301840191848101908884111561108d575f80fd5b938501935b838510156110b757845192506110a783610da3565b8282529385019390850190611092565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f80608085870312156110ea575f80fd5b505082516020840151604085015160609095015191969095509092509050565b6001600160a01b03848116825283166020820152606081016002831061113e57634e487b7160e01b5f52602160045260245ffd5b826040830152949350505050565b5f6020828403121561115c575f80fd5b5051919050565b5f60208284031215611173575f80fd5b815161029281610da3565b5f806040838503121561118f575f80fd5b505080516020909101519092909150565b5f60208083850312156111b1575f80fd5b825167ffffffffffffffff808211156111c8575f80fd5b818501915085601f8301126111db575f80fd5b8151818111156111ed576111ed610fd1565b6111ff601f8201601f19168501610fe5565b91508082528684828501011115611214575f80fd5b808484018584015e5f90820190930192909252509392505050565b5f6020828403121561123f575f80fd5b815160ff81168114610292575f80fd5b5f8261126957634e487b7160e01b5f52601260045260245ffd5b500490565b5f82518060208501845e5f920191825250919050565b80820281158282048414176101c657634e487b7160e01b5f52601160045260245ffd5b602081525f6102926020830184610df156fea2646970667358221220061cabf537e7b384ce2bf50908912924989afd923ae63da282423eafd6f69aff64736f6c63430008190033", "devdoc": { "kind": "dev", "methods": {}, diff --git a/deployments/bsctestnet/Unitroller_Implementation.json b/deployments/bsctestnet/Unitroller_Implementation.json index b728a9672..4dc498929 100644 --- a/deployments/bsctestnet/Unitroller_Implementation.json +++ b/deployments/bsctestnet/Unitroller_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0x1774f993861B14B7C3963F3e09f67cfBd2B32198", + "address": "0xf00Ba2930E43C96719Ca40c8B5a48F4c9A004c52", "abi": [ { "anonymous": false, @@ -218,6 +218,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -911,28 +924,28 @@ "type": "function" } ], - "transactionHash": "0xd081352d7b7b595c5fd01b6779b09ff0afa80219e813f26ebf6897b21b70b075", + "transactionHash": "0xcd1adc57fb136d663bdddcf6d7065501a4c785f703e212294486e0e0ce5c0cf6", "receipt": { "to": null, - "from": "0x33C6476F88eeA28D7E7900F759B4597704Ef95B7", - "contractAddress": "0x1774f993861B14B7C3963F3e09f67cfBd2B32198", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0xf00Ba2930E43C96719Ca40c8B5a48F4c9A004c52", "transactionIndex": 0, - "gasUsed": "1827052", + "gasUsed": "1837825", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x3663fb74dc58b1bb7a28e9b7033144edfcf1c7624ffaed0fc6175964a2667de2", - "transactionHash": "0xd081352d7b7b595c5fd01b6779b09ff0afa80219e813f26ebf6897b21b70b075", + "blockHash": "0xc8d57602556e70fc516ebf646cf5ba629dcbabcc32a87ca5af7e603d13a2972b", + "transactionHash": "0xcd1adc57fb136d663bdddcf6d7065501a4c785f703e212294486e0e0ce5c0cf6", "logs": [], - "blockNumber": 70271704, - "cumulativeGasUsed": "1827052", + "blockNumber": 102773907, + "cumulativeGasUsed": "1837825", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 7, - "solcInputHash": "4bb5f4f42cd6fd146f27cc1c5580cf4d", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"indexed\":false,\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"}],\"name\":\"DiamondCut\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"diamondCut_\",\"type\":\"tuple[]\"}],\"name\":\"diamondCut\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"functionSelector\",\"type\":\"bytes4\"}],\"name\":\"facetAddress\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"functionSelectorPosition\",\"type\":\"uint96\"}],\"internalType\":\"struct ComptrollerV13Storage.FacetAddressAndPosition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facetAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"facet\",\"type\":\"address\"}],\"name\":\"facetFunctionSelectors\",\"outputs\":[{\"internalType\":\"bytes4[]\",\"name\":\"\",\"type\":\"bytes4[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"facet\",\"type\":\"address\"}],\"name\":\"facetPosition\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facets\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct Diamond.Facet[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"_become(address)\":{\"params\":{\"unitroller\":\"Address of the unitroller\"}},\"diamondCut((address,uint8,bytes4[])[])\":{\"details\":\"Allows the contract admin to add function selectors\",\"params\":{\"diamondCut_\":\"IDiamondCut contains facets address, action and function selectors\"}},\"facetAddress(bytes4)\":{\"params\":{\"functionSelector\":\"function selector\"},\"returns\":{\"_0\":\"FacetAddressAndPosition facet address and position\"}},\"facetAddresses()\":{\"returns\":{\"_0\":\"facetAddresses Array of facet addresses\"}},\"facetFunctionSelectors(address)\":{\"params\":{\"facet\":\"Address of the facet\"},\"returns\":{\"_0\":\"selectors Array of function selectors\"}},\"facetPosition(address)\":{\"params\":{\"facet\":\"Address of the facet\"},\"returns\":{\"_0\":\"Position of the facet\"}},\"facets()\":{\"returns\":{\"_0\":\"facets_ Array of Facet\"}}},\"title\":\"Diamond\",\"version\":1},\"userdoc\":{\"events\":{\"DiamondCut((address,uint8,bytes4[])[])\":{\"notice\":\"Emitted when functions are added, replaced or removed to facets\"}},\"kind\":\"user\",\"methods\":{\"_become(address)\":{\"notice\":\"Call _acceptImplementation to accept the diamond proxy as new implementaion\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"diamondCut((address,uint8,bytes4[])[])\":{\"notice\":\"To add function selectors to the facet's mapping\"},\"facetAddress(bytes4)\":{\"notice\":\"Get facet address and position through function selector\"},\"facetAddresses()\":{\"notice\":\"Get all facet addresses\"},\"facetFunctionSelectors(address)\":{\"notice\":\"Get all function selectors mapped to the facet address\"},\"facetPosition(address)\":{\"notice\":\"Get facet position in the _facetFunctionSelectors through facet address\"},\"facets()\":{\"notice\":\"Get all facets address and their function selector\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This contract contains functions related to facets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/Diamond.sol\":\"Diamond\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x8a61b637428fbd7b7dcdc3098e40f7f70da4100bda9017b37e1f414399d20d49\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\",\"keccak256\":\"0x58576f27e672e8959a93e0b6bfb63743557d11c6e7a0ed032aaf5eec80b871dc\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/Diamond.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IDiamondCut } from \\\"./interfaces/IDiamondCut.sol\\\";\\nimport { Unitroller } from \\\"../Unitroller.sol\\\";\\nimport { ComptrollerV18Storage } from \\\"../ComptrollerStorage.sol\\\";\\n\\n/**\\n * @title Diamond\\n * @author Venus\\n * @notice This contract contains functions related to facets\\n */\\ncontract Diamond is IDiamondCut, ComptrollerV18Storage {\\n /// @notice Emitted when functions are added, replaced or removed to facets\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut);\\n\\n struct Facet {\\n address facetAddress;\\n bytes4[] functionSelectors;\\n }\\n\\n /**\\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\\n * @param unitroller Address of the unitroller\\n */\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"not authorized\\\");\\n }\\n\\n /**\\n * @notice To add function selectors to the facet's mapping\\n * @dev Allows the contract admin to add function selectors\\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\\n */\\n function diamondCut(IDiamondCut.FacetCut[] memory diamondCut_) public {\\n require(msg.sender == admin, \\\"only unitroller admin can\\\");\\n libDiamondCut(diamondCut_);\\n }\\n\\n /**\\n * @notice Get all function selectors mapped to the facet address\\n * @param facet Address of the facet\\n * @return selectors Array of function selectors\\n */\\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\\n return _facetFunctionSelectors[facet].functionSelectors;\\n }\\n\\n /**\\n * @notice Get facet position in the _facetFunctionSelectors through facet address\\n * @param facet Address of the facet\\n * @return Position of the facet\\n */\\n function facetPosition(address facet) external view returns (uint256) {\\n return _facetFunctionSelectors[facet].facetAddressPosition;\\n }\\n\\n /**\\n * @notice Get all facet addresses\\n * @return facetAddresses Array of facet addresses\\n */\\n function facetAddresses() external view returns (address[] memory) {\\n return _facetAddresses;\\n }\\n\\n /**\\n * @notice Get facet address and position through function selector\\n * @param functionSelector function selector\\n * @return FacetAddressAndPosition facet address and position\\n */\\n function facetAddress(\\n bytes4 functionSelector\\n ) external view returns (ComptrollerV18Storage.FacetAddressAndPosition memory) {\\n return _selectorToFacetAndPosition[functionSelector];\\n }\\n\\n /**\\n * @notice Get all facets address and their function selector\\n * @return facets_ Array of Facet\\n */\\n function facets() external view returns (Facet[] memory) {\\n uint256 facetsLength = _facetAddresses.length;\\n Facet[] memory facets_ = new Facet[](facetsLength);\\n for (uint256 i; i < facetsLength; ++i) {\\n address facet = _facetAddresses[i];\\n facets_[i].facetAddress = facet;\\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\\n }\\n return facets_;\\n }\\n\\n /**\\n * @notice To add function selectors to the facets' mapping\\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\\n */\\n function libDiamondCut(IDiamondCut.FacetCut[] memory diamondCut_) internal {\\n uint256 diamondCutLength = diamondCut_.length;\\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\\n IDiamondCut.FacetCutAction action = diamondCut_[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(diamondCut_);\\n }\\n\\n /**\\n * @notice Add function selectors to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to add in the mapping\\n */\\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n require(functionSelectors.length != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n require(facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(facetAddress);\\n }\\n uint256 functionSelectorsLength = functionSelectors.length;\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(selector, selectorPosition, facetAddress);\\n ++selectorPosition;\\n }\\n }\\n\\n /**\\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to replace in the mapping\\n */\\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n require(functionSelectors.length != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n require(facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(facetAddress);\\n }\\n uint256 functionSelectorsLength = functionSelectors.length;\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(oldFacetAddress, selector);\\n addFunction(selector, selectorPosition, facetAddress);\\n ++selectorPosition;\\n }\\n }\\n\\n /**\\n * @notice Remove function selectors to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to remove in the mapping\\n */\\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n uint256 functionSelectorsLength = functionSelectors.length;\\n require(functionSelectorsLength != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n // if function does not exist then do nothing and revert\\n require(facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(oldFacetAddress, selector);\\n }\\n }\\n\\n /**\\n * @notice Add new facet to the proxy\\n * @param facetAddress Address of the facet\\n */\\n function addFacet(address facetAddress) internal {\\n enforceHasContractCode(facetAddress, \\\"Diamond: New facet has no code\\\");\\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\\n _facetAddresses.push(facetAddress);\\n }\\n\\n /**\\n * @notice Add function selector to the facet's address mapping\\n * @param selector funciton selector need to be added\\n * @param selectorPosition funciton selector position\\n * @param facetAddress Address of the facet\\n */\\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\\n }\\n\\n /**\\n * @notice Remove function selector to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param selector function selectors need to remove in the mapping\\n */\\n function removeFunction(address facetAddress, bytes4 selector) internal {\\n require(facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\\n // if not the same then replace selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\\n delete _selectorToFacetAndPosition[selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n _facetAddresses.pop();\\n delete _facetFunctionSelectors[facetAddress];\\n }\\n }\\n\\n /**\\n * @dev Ensure that the given address has contract code deployed\\n * @param _contract The address to check for contract code\\n * @param _errorMessage The error message to display if the contract code is not deployed\\n */\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize != 0, _errorMessage);\\n }\\n\\n // Find facet for function that is called and execute the\\n // function if a facet is found and return any value.\\n fallback() external {\\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\\n require(facet != address(0), \\\"Diamond: Function does not exist\\\");\\n // Execute public function from facet using delegatecall and return any value.\\n assembly {\\n // copy function selector and any arguments\\n calldatacopy(0, 0, calldatasize())\\n // execute function call using the facet\\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\\n // get any return value\\n returndatacopy(0, 0, returndatasize())\\n // return any return value or error back to the caller\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x095890007d044e6b2cd9a61f96c64508f3ff5de9227147402a28de084eafe72b\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n function diamondCut(FacetCut[] calldata _diamondCut) external;\\n}\\n\",\"keccak256\":\"0xcb93543c9122cf328715d2b242e99f8ca234bd1347d82290ad7a4e028f358141\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Unitroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { UnitrollerAdminStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../Utils/ErrorReporter.sol\\\";\\n\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * VTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n fallback() external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize())\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize())\\n }\\n default {\\n return(free_mem_ptr, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7e552ae197db0095044af62614b09426d3570bf15593aa7703be3a517287074b\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xb590faa823e9359352775e0cc91ad34b04697936526f7b78fabfdec9d0f33ce4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[46] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1dfc20e742102201f642f0d7f4c0763983e64d8ce64a0b12b4ac923770c4c49a\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b5061200b8061001c5f395ff3fe608060405234801561000f575f80fd5b50600436106102ef575f3560e01c80638c1ac18a1161019b578063c5f956af116100e7578063e0f6123d116100a0578063e87554461161007a578063e8755446146108fe578063f445d70314610907578063f851a44014610934578063fa6331d814610946576102ef565b8063e0f6123d14610892578063e37d4b79146108b4578063e57e69c6146108eb576102ef565b8063c5f956af1461079d578063c7ee005e146107b0578063cdffacc6146107c3578063d3270f9914610859578063dce154491461086c578063dcfbc0c71461087f576102ef565b8063a657e57911610154578063b8324c7c1161012e578063b8324c7c14610707578063bb82aa5e14610762578063bbb8864a14610775578063bec04f7214610794576102ef565b8063a657e579146106c1578063adfca15e146106d4578063b2eafc39146106f4576102ef565b80638c1ac18a146106235780638f738f36146106455780639254f5e51461067057806394b2294b1461068357806396c990641461068c5780639bb27d62146106ae576102ef565b8063425fad581161025a57806373769099116102135780637d172bd5116101ed5780637d172bd5146105d15780637dc0d1d0146105e45780637fb8e8cd146105f75780638a7dc16514610604576102ef565b8063737690991461056a57806376551383146105aa5780637a0ed627146105bc576102ef565b8063425fad58146104e85780634a584432146104fb57806352d84d1e1461051a57806352ef6b2c1461052d5780635dd3fc9d14610542578063719f701b14610561576102ef565b806321af4569116102ac57806321af45691461044157806324a3d6221461046c578063267822471461047f5780632bc7e29e146104925780634088c73e146104b157806341a18d2c146104be576102ef565b806302c3bcbb1461038357806304ef9d58146103b557806308e0225c146103be5780630db4b4e5146103e857806310b98338146103f15780631d504dc61461042e575b5f80356001600160e01b0319168152602e60205260409020546001600160a01b0316806103635760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b365f80375f80365f845af43d5f803e80801561037d573d5ff35b3d5ffd5b005b6103a2610391366004611939565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103a260225481565b6103a26103cc36600461195b565b601360209081525f928352604080842090915290825290205481565b6103a2601d5481565b61041e6103ff36600461195b565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103ac565b61038161043c366004611939565b61094f565b601e54610454906001600160a01b031681565b6040516001600160a01b0390911681526020016103ac565b600a54610454906001600160a01b031681565b600154610454906001600160a01b031681565b6103a26104a0366004611939565b60166020525f908152604090205481565b60185461041e9060ff1681565b6103a26104cc36600461195b565b601260209081525f928352604080842090915290825290205481565b60185461041e9062010000900460ff1681565b6103a2610509366004611939565b601f6020525f908152604090205481565b610454610528366004611992565b610aad565b610535610ad5565b6040516103ac91906119a9565b6103a2610550366004611939565b602b6020525f908152604090205481565b6103a2601c5481565b610592610578366004611939565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103ac565b60185461041e90610100900460ff1681565b6105c4610b35565b6040516103ac9190611a39565b601b54610454906001600160a01b031681565b600454610454906001600160a01b031681565b60395461041e9060ff1681565b6103a2610612366004611939565b60146020525f908152604090205481565b61041e610631366004611939565b602d6020525f908152604090205460ff1681565b6103a2610653366004611939565b6001600160a01b03165f908152602f602052604090206001015490565b601554610454906001600160a01b031681565b6103a260075481565b61069f61069a366004611ab6565b610cb9565b6040516103ac93929190611b0a565b602554610454906001600160a01b031681565b603754610592906001600160601b031681565b6106e76106e2366004611939565b610d66565b6040516103ac9190611b33565b602054610454906001600160a01b031681565b61073e610715366004611939565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103ac565b600254610454906001600160a01b031681565b6103a2610783366004611939565b602a6020525f908152604090205481565b6103a260175481565b602154610454906001600160a01b031681565b603154610454906001600160a01b031681565b61082c6107d1366004611b61565b604080518082019091525f8082526020820152506001600160e01b0319165f908152602e60209081526040918290208251808401909352546001600160a01b0381168352600160a01b90046001600160601b03169082015290565b6040805182516001600160a01b031681526020928301516001600160601b031692810192909252016103ac565b602654610454906001600160a01b031681565b61045461087a366004611b7a565b610dfb565b600354610454906001600160a01b031681565b61041e6108a0366004611939565b60386020525f908152604090205460ff1681565b61073e6108c2366004611939565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6103816108f9366004611c35565b610e2f565b6103a260055481565b61041e61091536600461195b565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610454906001600160a01b031681565b6103a2601a5481565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109af9190611d9b565b6001600160a01b0316336001600160a01b031614610a0b5760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b604482015260640161035a565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6c9190611db6565b15610aaa5760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b604482015260640161035a565b50565b600d8181548110610abc575f80fd5b5f918252602090912001546001600160a01b0316905081565b60606030805480602002602001604051908101604052809291908181526020018280548015610b2b57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610b0d575b5050505050905090565b6030546060905f8167ffffffffffffffff811115610b5557610b55611ba4565b604051908082528060200260200182016040528015610b9a57816020015b604080518082019091525f815260606020820152815260200190600190039081610b735790505b5090505f5b82811015610cb2575f60308281548110610bbb57610bbb611dcd565b905f5260205f20015f9054906101000a90046001600160a01b0316905080838381518110610beb57610beb611dcd565b6020908102919091018101516001600160a01b0392831690529082165f908152602f825260409081902080548251818502810185019093528083529192909190830182828015610c8457602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610c465790505b5050505050838381518110610c9b57610c9b611dcd565b602090810291909101810151015250600101610b9f565b5092915050565b60366020525f9081526040902080548190610cd390611de1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cff90611de1565b8015610d4a5780601f10610d2157610100808354040283529160200191610d4a565b820191905f5260205f20905b815481529060010190602001808311610d2d57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6001600160a01b0381165f908152602f6020908152604091829020805483518184028101840190945280845260609392830182828015610def57602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610db15790505b50505050509050919050565b6008602052815f5260405f208181548110610e14575f80fd5b5f918252602090912001546001600160a01b03169150829050565b5f546001600160a01b03163314610e845760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b604482015260640161035a565b610aaa8180515f5b8181101561103f575f838281518110610ea757610ea7611dcd565b60200260200101516020015190505f6002811115610ec757610ec7611e19565b816002811115610ed957610ed9611e19565b03610f2657610f21848381518110610ef357610ef3611dcd565b60200260200101515f0151858481518110610f1057610f10611dcd565b60200260200101516040015161107b565b611036565b6001816002811115610f3a57610f3a611e19565b03610f8257610f21848381518110610f5457610f54611dcd565b60200260200101515f0151858481518110610f7157610f71611dcd565b6020026020010151604001516111da565b6002816002811115610f9657610f96611e19565b03610fde57610f21848381518110610fb057610fb0611dcd565b60200260200101515f0151858481518110610fcd57610fcd611dcd565b602002602001015160400151611349565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b606482015260840161035a565b50600101610e8c565b507f2e97860c6f47eab0292d51fa3ceec7e373c62af1e7eb2a28ae82998b80de6cfd8260405161106f9190611e2d565b60405180910390a15050565b80515f0361109b5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b0382166110c15760405162461bcd60e51b815260040161035a90611f11565b6001600160a01b0382165f908152602f6020526040812054906001600160601b03821690036110f3576110f38361144a565b81515f5b818110156111d3575f84828151811061111257611112611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031680156111b05760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b606482015260840161035a565b6111bb8286896114ec565b6111c485611f71565b945050508060010190506110f7565b5050505050565b80515f036111fa5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b0382166112205760405162461bcd60e51b815260040161035a90611f11565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611252576112528361144a565b81515f5b818110156111d3575f84828151811061127157611271611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b03908116908716810361131c5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606482015260840161035a565b611326818361158a565b6113318286896114ec565b61133a85611f71565b94505050806001019050611256565b80515f81900361136b5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b038316156113e15760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b606482015260840161035a565b5f5b81811015611444575f8382815181106113fe576113fe611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031661143a818361158a565b50506001016113e3565b50505050565b611489816040518060400160405280601e81526020017f4469616d6f6e643a204e657720666163657420686173206e6f20636f646500008152506118cf565b603080546001600160a01b039092165f818152602f60205260408120600190810185905584018355919091527f6ff97a59c90d62cc7236ba3a37cd85351bf564556780cf8c1157a220f31f0cbb90910180546001600160a01b0319169091179055565b6001600160e01b031983165f818152602e6020818152604080842080546001600160601b03909816600160a01b026001600160a01b0398891617815595909616808452602f825295832080546001810182559084528184206008820401805460e09990991c60046007909316929092026101000a91820263ffffffff909202199098161790965591905290925281546001600160a01b031916179055565b6001600160a01b0382166116065760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606482015260840161035a565b6001600160e01b031981165f908152602e60209081526040808320546001600160a01b0386168452602f909252822054600160a01b9091046001600160601b0316919061165590600190611f96565b9050808214611741576001600160a01b0384165f908152602f6020526040812080548390811061168757611687611dcd565b5f91825260208083206008830401546001600160a01b0389168452602f9091526040909220805460079092166004026101000a90920460e01b9250829190859081106116d5576116d5611dcd565b5f91825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b0319929092168252602e90526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384165f908152602f6020526040902080548061176757611767611faf565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252602e905260408120819055819003611444576030545f906117c690600190611f96565b6001600160a01b0386165f908152602f602052604090206001015490915080821461186a575f603083815481106117ff576117ff611dcd565b5f91825260209091200154603080546001600160a01b03909216925082918490811061182d5761182d611dcd565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152602f909152604090206001018190555b603080548061187b5761187b611faf565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092556001600160a01b0388168252602f905260408120906118be82826118f0565b600182015f90555050505050505050565b813b81816114445760405162461bcd60e51b815260040161035a9190611fc3565b5080545f825560070160089004905f5260205f2090810190610aaa91905b80821115611921575f815560010161190e565b5090565b6001600160a01b0381168114610aaa575f80fd5b5f60208284031215611949575f80fd5b813561195481611925565b9392505050565b5f806040838503121561196c575f80fd5b823561197781611925565b9150602083013561198781611925565b809150509250929050565b5f602082840312156119a2575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b818110156119e95783516001600160a01b0316835292840192918401916001016119c4565b50909695505050505050565b5f815180845260208085019450602084015f5b83811015611a2e5781516001600160e01b03191687529582019590820190600101611a08565b509495945050505050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611aa857888303603f19018552815180516001600160a01b03168452870151878401879052611a95878501826119f5565b9588019593505090860190600101611a60565b509098975050505050505050565b5f60208284031215611ac6575f80fd5b81356001600160601b0381168114611954575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f611b1c6060830186611adc565b931515602083015250901515604090910152919050565b602081525f61195460208301846119f5565b80356001600160e01b031981168114611b5c575f80fd5b919050565b5f60208284031215611b71575f80fd5b61195482611b45565b5f8060408385031215611b8b575f80fd5b8235611b9681611925565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611bdb57611bdb611ba4565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c0a57611c0a611ba4565b604052919050565b5f67ffffffffffffffff821115611c2b57611c2b611ba4565b5060051b60200190565b5f6020808385031215611c46575f80fd5b823567ffffffffffffffff80821115611c5d575f80fd5b818501915085601f830112611c70575f80fd5b8135611c83611c7e82611c12565b611be1565b81815260059190911b83018401908481019088831115611ca1575f80fd5b8585015b83811015611d8e57803585811115611cbb575f80fd5b86016060818c03601f1901811315611cd1575f80fd5b611cd9611bb8565b89830135611ce681611925565b815260408381013560038110611cfa575f80fd5b828c0152918301359188831115611d0f575f80fd5b82840193508d603f850112611d22575f80fd5b8a8401359250611d34611c7e84611c12565b83815260059390931b84018101928b8101908f851115611d52575f80fd5b948201945b84861015611d7757611d6886611b45565b8252948c0194908c0190611d57565b918301919091525085525050918601918601611ca5565b5098975050505050505050565b5f60208284031215611dab575f80fd5b815161195481611925565b5f60208284031215611dc6575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680611df557607f821691505b602082108103611e1357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611aa857888303603f19018552815180516001600160a01b031684528781015160609060038110611e9757634e487b7160e01b5f52602160045260245ffd5b858a01529087015187850182905290611eb2818601836119f5565b968901969450505090860190600101611e54565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160601b03808316818103611f8c57611f8c611f5d565b6001019392505050565b81810381811115611fa957611fa9611f5d565b92915050565b634e487b7160e01b5f52603160045260245ffd5b602081525f6119546020830184611adc56fea2646970667358221220a6be7462800b74f95572f969b57a5a0d99898d128b76aa663e604dc84fd8cbca64736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b50600436106102ef575f3560e01c80638c1ac18a1161019b578063c5f956af116100e7578063e0f6123d116100a0578063e87554461161007a578063e8755446146108fe578063f445d70314610907578063f851a44014610934578063fa6331d814610946576102ef565b8063e0f6123d14610892578063e37d4b79146108b4578063e57e69c6146108eb576102ef565b8063c5f956af1461079d578063c7ee005e146107b0578063cdffacc6146107c3578063d3270f9914610859578063dce154491461086c578063dcfbc0c71461087f576102ef565b8063a657e57911610154578063b8324c7c1161012e578063b8324c7c14610707578063bb82aa5e14610762578063bbb8864a14610775578063bec04f7214610794576102ef565b8063a657e579146106c1578063adfca15e146106d4578063b2eafc39146106f4576102ef565b80638c1ac18a146106235780638f738f36146106455780639254f5e51461067057806394b2294b1461068357806396c990641461068c5780639bb27d62146106ae576102ef565b8063425fad581161025a57806373769099116102135780637d172bd5116101ed5780637d172bd5146105d15780637dc0d1d0146105e45780637fb8e8cd146105f75780638a7dc16514610604576102ef565b8063737690991461056a57806376551383146105aa5780637a0ed627146105bc576102ef565b8063425fad58146104e85780634a584432146104fb57806352d84d1e1461051a57806352ef6b2c1461052d5780635dd3fc9d14610542578063719f701b14610561576102ef565b806321af4569116102ac57806321af45691461044157806324a3d6221461046c578063267822471461047f5780632bc7e29e146104925780634088c73e146104b157806341a18d2c146104be576102ef565b806302c3bcbb1461038357806304ef9d58146103b557806308e0225c146103be5780630db4b4e5146103e857806310b98338146103f15780631d504dc61461042e575b5f80356001600160e01b0319168152602e60205260409020546001600160a01b0316806103635760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b365f80375f80365f845af43d5f803e80801561037d573d5ff35b3d5ffd5b005b6103a2610391366004611939565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103a260225481565b6103a26103cc36600461195b565b601360209081525f928352604080842090915290825290205481565b6103a2601d5481565b61041e6103ff36600461195b565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103ac565b61038161043c366004611939565b61094f565b601e54610454906001600160a01b031681565b6040516001600160a01b0390911681526020016103ac565b600a54610454906001600160a01b031681565b600154610454906001600160a01b031681565b6103a26104a0366004611939565b60166020525f908152604090205481565b60185461041e9060ff1681565b6103a26104cc36600461195b565b601260209081525f928352604080842090915290825290205481565b60185461041e9062010000900460ff1681565b6103a2610509366004611939565b601f6020525f908152604090205481565b610454610528366004611992565b610aad565b610535610ad5565b6040516103ac91906119a9565b6103a2610550366004611939565b602b6020525f908152604090205481565b6103a2601c5481565b610592610578366004611939565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103ac565b60185461041e90610100900460ff1681565b6105c4610b35565b6040516103ac9190611a39565b601b54610454906001600160a01b031681565b600454610454906001600160a01b031681565b60395461041e9060ff1681565b6103a2610612366004611939565b60146020525f908152604090205481565b61041e610631366004611939565b602d6020525f908152604090205460ff1681565b6103a2610653366004611939565b6001600160a01b03165f908152602f602052604090206001015490565b601554610454906001600160a01b031681565b6103a260075481565b61069f61069a366004611ab6565b610cb9565b6040516103ac93929190611b0a565b602554610454906001600160a01b031681565b603754610592906001600160601b031681565b6106e76106e2366004611939565b610d66565b6040516103ac9190611b33565b602054610454906001600160a01b031681565b61073e610715366004611939565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103ac565b600254610454906001600160a01b031681565b6103a2610783366004611939565b602a6020525f908152604090205481565b6103a260175481565b602154610454906001600160a01b031681565b603154610454906001600160a01b031681565b61082c6107d1366004611b61565b604080518082019091525f8082526020820152506001600160e01b0319165f908152602e60209081526040918290208251808401909352546001600160a01b0381168352600160a01b90046001600160601b03169082015290565b6040805182516001600160a01b031681526020928301516001600160601b031692810192909252016103ac565b602654610454906001600160a01b031681565b61045461087a366004611b7a565b610dfb565b600354610454906001600160a01b031681565b61041e6108a0366004611939565b60386020525f908152604090205460ff1681565b61073e6108c2366004611939565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b6103816108f9366004611c35565b610e2f565b6103a260055481565b61041e61091536600461195b565b603260209081525f928352604080842090915290825290205460ff1681565b5f54610454906001600160a01b031681565b6103a2601a5481565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa15801561098b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109af9190611d9b565b6001600160a01b0316336001600160a01b031614610a0b5760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b604482015260640161035a565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a6c9190611db6565b15610aaa5760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b604482015260640161035a565b50565b600d8181548110610abc575f80fd5b5f918252602090912001546001600160a01b0316905081565b60606030805480602002602001604051908101604052809291908181526020018280548015610b2b57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610b0d575b5050505050905090565b6030546060905f8167ffffffffffffffff811115610b5557610b55611ba4565b604051908082528060200260200182016040528015610b9a57816020015b604080518082019091525f815260606020820152815260200190600190039081610b735790505b5090505f5b82811015610cb2575f60308281548110610bbb57610bbb611dcd565b905f5260205f20015f9054906101000a90046001600160a01b0316905080838381518110610beb57610beb611dcd565b6020908102919091018101516001600160a01b0392831690529082165f908152602f825260409081902080548251818502810185019093528083529192909190830182828015610c8457602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610c465790505b5050505050838381518110610c9b57610c9b611dcd565b602090810291909101810151015250600101610b9f565b5092915050565b60366020525f9081526040902080548190610cd390611de1565b80601f0160208091040260200160405190810160405280929190818152602001828054610cff90611de1565b8015610d4a5780601f10610d2157610100808354040283529160200191610d4a565b820191905f5260205f20905b815481529060010190602001808311610d2d57829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6001600160a01b0381165f908152602f6020908152604091829020805483518184028101840190945280845260609392830182828015610def57602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610db15790505b50505050509050919050565b6008602052815f5260405f208181548110610e14575f80fd5b5f918252602090912001546001600160a01b03169150829050565b5f546001600160a01b03163314610e845760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b604482015260640161035a565b610aaa8180515f5b8181101561103f575f838281518110610ea757610ea7611dcd565b60200260200101516020015190505f6002811115610ec757610ec7611e19565b816002811115610ed957610ed9611e19565b03610f2657610f21848381518110610ef357610ef3611dcd565b60200260200101515f0151858481518110610f1057610f10611dcd565b60200260200101516040015161107b565b611036565b6001816002811115610f3a57610f3a611e19565b03610f8257610f21848381518110610f5457610f54611dcd565b60200260200101515f0151858481518110610f7157610f71611dcd565b6020026020010151604001516111da565b6002816002811115610f9657610f96611e19565b03610fde57610f21848381518110610fb057610fb0611dcd565b60200260200101515f0151858481518110610fcd57610fcd611dcd565b602002602001015160400151611349565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b606482015260840161035a565b50600101610e8c565b507f2e97860c6f47eab0292d51fa3ceec7e373c62af1e7eb2a28ae82998b80de6cfd8260405161106f9190611e2d565b60405180910390a15050565b80515f0361109b5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b0382166110c15760405162461bcd60e51b815260040161035a90611f11565b6001600160a01b0382165f908152602f6020526040812054906001600160601b03821690036110f3576110f38361144a565b81515f5b818110156111d3575f84828151811061111257611112611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031680156111b05760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b606482015260840161035a565b6111bb8286896114ec565b6111c485611f71565b945050508060010190506110f7565b5050505050565b80515f036111fa5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b0382166112205760405162461bcd60e51b815260040161035a90611f11565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611252576112528361144a565b81515f5b818110156111d3575f84828151811061127157611271611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b03908116908716810361131c5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e0000000000000000606482015260840161035a565b611326818361158a565b6113318286896114ec565b61133a85611f71565b94505050806001019050611256565b80515f81900361136b5760405162461bcd60e51b815260040161035a90611ec6565b6001600160a01b038316156113e15760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b606482015260840161035a565b5f5b81811015611444575f8382815181106113fe576113fe611dcd565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031661143a818361158a565b50506001016113e3565b50505050565b611489816040518060400160405280601e81526020017f4469616d6f6e643a204e657720666163657420686173206e6f20636f646500008152506118cf565b603080546001600160a01b039092165f818152602f60205260408120600190810185905584018355919091527f6ff97a59c90d62cc7236ba3a37cd85351bf564556780cf8c1157a220f31f0cbb90910180546001600160a01b0319169091179055565b6001600160e01b031983165f818152602e6020818152604080842080546001600160601b03909816600160a01b026001600160a01b0398891617815595909616808452602f825295832080546001810182559084528184206008820401805460e09990991c60046007909316929092026101000a91820263ffffffff909202199098161790965591905290925281546001600160a01b031916179055565b6001600160a01b0382166116065760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e2774206578697374000000000000000000606482015260840161035a565b6001600160e01b031981165f908152602e60209081526040808320546001600160a01b0386168452602f909252822054600160a01b9091046001600160601b0316919061165590600190611f96565b9050808214611741576001600160a01b0384165f908152602f6020526040812080548390811061168757611687611dcd565b5f91825260208083206008830401546001600160a01b0389168452602f9091526040909220805460079092166004026101000a90920460e01b9250829190859081106116d5576116d5611dcd565b5f91825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b0319929092168252602e90526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384165f908152602f6020526040902080548061176757611767611faf565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252602e905260408120819055819003611444576030545f906117c690600190611f96565b6001600160a01b0386165f908152602f602052604090206001015490915080821461186a575f603083815481106117ff576117ff611dcd565b5f91825260209091200154603080546001600160a01b03909216925082918490811061182d5761182d611dcd565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152602f909152604090206001018190555b603080548061187b5761187b611faf565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092556001600160a01b0388168252602f905260408120906118be82826118f0565b600182015f90555050505050505050565b813b81816114445760405162461bcd60e51b815260040161035a9190611fc3565b5080545f825560070160089004905f5260205f2090810190610aaa91905b80821115611921575f815560010161190e565b5090565b6001600160a01b0381168114610aaa575f80fd5b5f60208284031215611949575f80fd5b813561195481611925565b9392505050565b5f806040838503121561196c575f80fd5b823561197781611925565b9150602083013561198781611925565b809150509250929050565b5f602082840312156119a2575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b818110156119e95783516001600160a01b0316835292840192918401916001016119c4565b50909695505050505050565b5f815180845260208085019450602084015f5b83811015611a2e5781516001600160e01b03191687529582019590820190600101611a08565b509495945050505050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611aa857888303603f19018552815180516001600160a01b03168452870151878401879052611a95878501826119f5565b9588019593505090860190600101611a60565b509098975050505050505050565b5f60208284031215611ac6575f80fd5b81356001600160601b0381168114611954575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f611b1c6060830186611adc565b931515602083015250901515604090910152919050565b602081525f61195460208301846119f5565b80356001600160e01b031981168114611b5c575f80fd5b919050565b5f60208284031215611b71575f80fd5b61195482611b45565b5f8060408385031215611b8b575f80fd5b8235611b9681611925565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611bdb57611bdb611ba4565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c0a57611c0a611ba4565b604052919050565b5f67ffffffffffffffff821115611c2b57611c2b611ba4565b5060051b60200190565b5f6020808385031215611c46575f80fd5b823567ffffffffffffffff80821115611c5d575f80fd5b818501915085601f830112611c70575f80fd5b8135611c83611c7e82611c12565b611be1565b81815260059190911b83018401908481019088831115611ca1575f80fd5b8585015b83811015611d8e57803585811115611cbb575f80fd5b86016060818c03601f1901811315611cd1575f80fd5b611cd9611bb8565b89830135611ce681611925565b815260408381013560038110611cfa575f80fd5b828c0152918301359188831115611d0f575f80fd5b82840193508d603f850112611d22575f80fd5b8a8401359250611d34611c7e84611c12565b83815260059390931b84018101928b8101908f851115611d52575f80fd5b948201945b84861015611d7757611d6886611b45565b8252948c0194908c0190611d57565b918301919091525085525050918601918601611ca5565b5098975050505050505050565b5f60208284031215611dab575f80fd5b815161195481611925565b5f60208284031215611dc6575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680611df557607f821691505b602082108103611e1357634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611aa857888303603f19018552815180516001600160a01b031684528781015160609060038110611e9757634e487b7160e01b5f52602160045260245ffd5b858a01529087015187850182905290611eb2818601836119f5565b968901969450505090860190600101611e54565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160601b03808316818103611f8c57611f8c611f5d565b6001019392505050565b81810381811115611fa957611fa9611f5d565b92915050565b634e487b7160e01b5f52603160045260245ffd5b602081525f6119546020830184611adc56fea2646970667358221220a6be7462800b74f95572f969b57a5a0d99898d128b76aa663e604dc84fd8cbca64736f6c63430008190033", + "numDeployments": 8, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"indexed\":false,\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"}],\"name\":\"DiamondCut\",\"type\":\"event\"},{\"stateMutability\":\"nonpayable\",\"type\":\"fallback\"},{\"inputs\":[{\"internalType\":\"contract Unitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"accountAssets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"allMarkets\",\"outputs\":[{\"internalType\":\"contract VToken\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"approvedDelegates\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"authorizedFlashLoan\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"borrowCapGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"borrowCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"closeFactorMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptrollerLens\",\"outputs\":[{\"internalType\":\"contract ComptrollerLensInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"deviationBoundedOracle\",\"outputs\":[{\"internalType\":\"contract IDeviationBoundedOracle\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"diamondCut_\",\"type\":\"tuple[]\"}],\"name\":\"diamondCut\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"functionSelector\",\"type\":\"bytes4\"}],\"name\":\"facetAddress\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"uint96\",\"name\":\"functionSelectorPosition\",\"type\":\"uint96\"}],\"internalType\":\"struct ComptrollerV13Storage.FacetAddressAndPosition\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facetAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"facet\",\"type\":\"address\"}],\"name\":\"facetFunctionSelectors\",\"outputs\":[{\"internalType\":\"bytes4[]\",\"name\":\"\",\"type\":\"bytes4[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"facet\",\"type\":\"address\"}],\"name\":\"facetPosition\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facets\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct Diamond.Facet[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"flashLoanPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabled\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"market\",\"type\":\"address\"}],\"name\":\"isForcedLiquidationEnabledForUser\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"lastPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"liquidatorContract\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxAssets\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"minReleaseAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"mintedVAIs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"oracle\",\"outputs\":[{\"internalType\":\"contract ResilientOracleInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pauseGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingComptrollerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"name\":\"pools\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"label\",\"type\":\"string\"},{\"internalType\":\"bool\",\"name\":\"isActive\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"allowCorePoolFallback\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"contract IPrime\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"protocolPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"releaseStartBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"repayVAIGuardianPaused\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"supplyCaps\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"userPoolId\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiController\",\"outputs\":[{\"internalType\":\"contract VAIControllerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiVaultAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusAccrued\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowSpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusBorrowerIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplierIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplySpeeds\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusSupplyState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIVaultRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"kind\":\"dev\",\"methods\":{\"_become(address)\":{\"params\":{\"unitroller\":\"Address of the unitroller\"}},\"diamondCut((address,uint8,bytes4[])[])\":{\"details\":\"Allows the contract admin to add function selectors\",\"params\":{\"diamondCut_\":\"IDiamondCut contains facets address, action and function selectors\"}},\"facetAddress(bytes4)\":{\"params\":{\"functionSelector\":\"function selector\"},\"returns\":{\"_0\":\"FacetAddressAndPosition facet address and position\"}},\"facetAddresses()\":{\"returns\":{\"_0\":\"facetAddresses Array of facet addresses\"}},\"facetFunctionSelectors(address)\":{\"params\":{\"facet\":\"Address of the facet\"},\"returns\":{\"_0\":\"selectors Array of function selectors\"}},\"facetPosition(address)\":{\"params\":{\"facet\":\"Address of the facet\"},\"returns\":{\"_0\":\"Position of the facet\"}},\"facets()\":{\"returns\":{\"_0\":\"facets_ Array of Facet\"}}},\"title\":\"Diamond\",\"version\":1},\"userdoc\":{\"events\":{\"DiamondCut((address,uint8,bytes4[])[])\":{\"notice\":\"Emitted when functions are added, replaced or removed to facets\"}},\"kind\":\"user\",\"methods\":{\"_become(address)\":{\"notice\":\"Call _acceptImplementation to accept the diamond proxy as new implementaion\"},\"accountAssets(address,uint256)\":{\"notice\":\"Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"allMarkets(uint256)\":{\"notice\":\"A list of all markets\"},\"approvedDelegates(address,address)\":{\"notice\":\"Whether the delegate is allowed to borrow or redeem on behalf of the user\"},\"authorizedFlashLoan(address)\":{\"notice\":\"Mapping of accounts authorized to execute flash loans\"},\"borrowCapGuardian()\":{\"notice\":\"The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\"},\"borrowCaps(address)\":{\"notice\":\"Borrow caps enforced by borrowAllowed for each vToken address.\"},\"closeFactorMantissa()\":{\"notice\":\"Multiplier used to calculate the maximum repayAmount when liquidating a borrow\"},\"comptrollerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"deviationBoundedOracle()\":{\"notice\":\"DeviationBoundedOracle for conservative pricing in CF path\"},\"diamondCut((address,uint8,bytes4[])[])\":{\"notice\":\"To add function selectors to the facet's mapping\"},\"facetAddress(bytes4)\":{\"notice\":\"Get facet address and position through function selector\"},\"facetAddresses()\":{\"notice\":\"Get all facet addresses\"},\"facetFunctionSelectors(address)\":{\"notice\":\"Get all function selectors mapped to the facet address\"},\"facetPosition(address)\":{\"notice\":\"Get facet position in the _facetFunctionSelectors through facet address\"},\"facets()\":{\"notice\":\"Get all facets address and their function selector\"},\"flashLoanPaused()\":{\"notice\":\"Whether flash loans are paused system-wide\"},\"isForcedLiquidationEnabled(address)\":{\"notice\":\"Whether forced liquidation is enabled for all users borrowing in a certain market\"},\"isForcedLiquidationEnabledForUser(address,address)\":{\"notice\":\"Whether forced liquidation is enabled for the borrows of a user in a market\"},\"lastPoolId()\":{\"notice\":\"Counter used to generate unique pool IDs\"},\"maxAssets()\":{\"notice\":\"Max number of assets a single account can participate in (borrow or use as collateral)\"},\"mintVAIGuardianPaused()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"mintedVAIs(address)\":{\"notice\":\"The minted VAI amount to each user\"},\"oracle()\":{\"notice\":\"Oracle which gives the price of any given asset\"},\"pauseGuardian()\":{\"notice\":\"The Pause Guardian can pause certain actions as a safety mechanism.\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingComptrollerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"pools(uint96)\":{\"notice\":\"Mapping of pool ID to its corresponding metadata and configuration\"},\"prime()\":{\"notice\":\"Prime token address\"},\"protocolPaused()\":{\"notice\":\"Pause/Unpause whole protocol actions\"},\"supplyCaps(address)\":{\"notice\":\"Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"userPoolId(address)\":{\"notice\":\"Tracks the selected pool for each user\"},\"vaiController()\":{\"notice\":\"The Address of VAIController\"},\"vaiMintRate()\":{\"notice\":\"VAI Mint Rate as a percentage\"},\"venusAccrued(address)\":{\"notice\":\"The XVS accrued but not yet transferred to each user\"},\"venusBorrowSpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding borrow market (per block)\"},\"venusBorrowState(address)\":{\"notice\":\"The Venus market borrow state for each market\"},\"venusBorrowerIndex(address,address)\":{\"notice\":\"The Venus borrow index for each market for each borrower as of the last time they accrued XVS\"},\"venusSupplierIndex(address,address)\":{\"notice\":\"The Venus supply index for each market for each supplier as of the last time they accrued XVS\"},\"venusSupplySpeeds(address)\":{\"notice\":\"The rate at which venus is distributed to the corresponding supply market (per block)\"},\"venusSupplyState(address)\":{\"notice\":\"The Venus market supply state for each market\"},\"venusVAIVaultRate()\":{\"notice\":\"The rate at which the flywheel distributes XVS to VAI Vault, per block\"}},\"notice\":\"This contract contains functions related to facets\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Comptroller/Diamond/Diamond.sol\":\"Diamond\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerLensInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\ninterface ComptrollerLensInterface {\\n function liquidateCalculateSeizeTokens(\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address comptroller,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address comptroller,\\n address vTokenCollateral,\\n uint actualRepayAmount\\n ) external view returns (uint, uint);\\n\\n function getHypotheticalAccountLiquidity(\\n address comptroller,\\n address account,\\n VToken vTokenModify,\\n uint redeemTokens,\\n uint borrowAmount,\\n WeightFunction weightingStrategy\\n ) external view returns (uint, uint, uint);\\n}\\n\",\"keccak256\":\"0x5613ff839f6aed74491f3248723c6c3d73e39fc9ec3ac5b2db5e605f14a89ac0\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\nimport { PoolMarketId } from \\\"./Types/PoolMarketId.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { ComptrollerLensInterface } from \\\"./ComptrollerLensInterface.sol\\\";\\nimport { IPrime } from \\\"../Tokens/Prime/IPrime.sol\\\";\\n\\ncontract UnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public comptrollerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingComptrollerImplementation;\\n}\\n\\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\\n /**\\n * @notice Oracle which gives the price of any given asset\\n */\\n ResilientOracleInterface public oracle;\\n\\n /**\\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\\n */\\n uint256 public closeFactorMantissa;\\n\\n /**\\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\\n */\\n uint256 private _oldLiquidationIncentiveMantissa;\\n\\n /**\\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\\n */\\n uint256 public maxAssets;\\n\\n /**\\n * @notice Per-account mapping of \\\"assets you are in\\\", capped by maxAssets\\n */\\n mapping(address => VToken[]) public accountAssets;\\n\\n struct Market {\\n /// @notice Whether or not this market is listed\\n bool isListed;\\n /**\\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\\n * For instance, 0.9 to allow borrowing 90% of collateral value.\\n * Must be between 0 and 1, and stored as a mantissa.\\n */\\n uint256 collateralFactorMantissa;\\n /// @notice Per-market mapping of \\\"accounts in this asset\\\" (used for Core Pool only)\\n mapping(address => bool) accountMembership;\\n /// @notice Whether or not this market receives XVS\\n bool isVenus;\\n /**\\n * @notice Multiplier representing the collateralization after which the borrow is eligible\\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\\n * value. Must be between 0 and collateral factor, stored as a mantissa.\\n */\\n uint256 liquidationThresholdMantissa;\\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\\n uint256 liquidationIncentiveMantissa;\\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\\n uint96 poolId;\\n /// @notice Flag to restrict borrowing in certain pools/emodes.\\n bool isBorrowAllowed;\\n }\\n\\n /**\\n * @notice Mapping of PoolMarketId -> Market metadata\\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\\n */\\n mapping(PoolMarketId => Market) internal _poolMarkets;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n address public pauseGuardian;\\n\\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\\n bool private _mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool private _borrowGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal transferGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n bool internal seizeGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal mintGuardianPaused;\\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\\n mapping(address => bool) internal borrowGuardianPaused;\\n\\n struct VenusMarketState {\\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice A list of all markets\\n VToken[] public allMarkets;\\n\\n /// @notice The rate at which the flywheel distributes XVS, per block\\n uint256 internal venusRate;\\n\\n /// @notice The portion of venusRate that each market currently receives\\n mapping(address => uint256) internal venusSpeeds;\\n\\n /// @notice The Venus market supply state for each market\\n mapping(address => VenusMarketState) public venusSupplyState;\\n\\n /// @notice The Venus market borrow state for each market\\n mapping(address => VenusMarketState) public venusBorrowState;\\n\\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\\n\\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\\n\\n /// @notice The XVS accrued but not yet transferred to each user\\n mapping(address => uint256) public venusAccrued;\\n\\n /// @notice The Address of VAIController\\n VAIControllerInterface public vaiController;\\n\\n /// @notice The minted VAI amount to each user\\n mapping(address => uint256) public mintedVAIs;\\n\\n /// @notice VAI Mint Rate as a percentage\\n uint256 public vaiMintRate;\\n\\n /**\\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\\n */\\n bool public mintVAIGuardianPaused;\\n bool public repayVAIGuardianPaused;\\n\\n /**\\n * @notice Pause/Unpause whole protocol actions\\n */\\n bool public protocolPaused;\\n\\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\\n uint256 private venusVAIRate;\\n}\\n\\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\\n uint256 public venusVAIVaultRate;\\n\\n // address of VAI Vault\\n address public vaiVaultAddress;\\n\\n // start block of release to VAI Vault\\n uint256 public releaseStartBlock;\\n\\n // minimum release amount to VAI Vault\\n uint256 public minReleaseAmount;\\n}\\n\\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\\n address public borrowCapGuardian;\\n\\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\\n mapping(address => uint256) public borrowCaps;\\n}\\n\\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n}\\n\\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\\n mapping(address => uint256) private venusContributorSpeeds;\\n\\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\\n mapping(address => uint256) private lastContributorBlock;\\n}\\n\\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\\n address public liquidatorContract;\\n}\\n\\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\\n ComptrollerLensInterface public comptrollerLens;\\n}\\n\\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\\n mapping(address => uint256) public supplyCaps;\\n}\\n\\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\\n /// @notice AccessControlManager address\\n address internal accessControl;\\n\\n /// @notice True if a certain action is paused on a certain market\\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\\n}\\n\\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\\n mapping(address => uint256) public venusBorrowSpeeds;\\n\\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\\n mapping(address => uint256) public venusSupplySpeeds;\\n}\\n\\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\\n mapping(address => mapping(address => bool)) public approvedDelegates;\\n}\\n\\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\\n mapping(address => bool) public isForcedLiquidationEnabled;\\n}\\n\\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\\n }\\n\\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\\n // facet addresses\\n address[] internal _facetAddresses;\\n}\\n\\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\\n /// @notice Prime token address\\n IPrime public prime;\\n}\\n\\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\\n}\\n\\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\\n /// @notice The XVS token contract address\\n address internal xvs;\\n\\n /// @notice The XVS vToken contract address\\n address internal xvsVToken;\\n}\\n\\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\\n struct PoolData {\\n /// @notice label for the pool\\n string label;\\n /// @notice List of vToken addresses associated with this pool\\n address[] vTokens;\\n /**\\n * @notice Whether the pool is active and can be entered. If set to false,\\n * new entries are disabled and existing accounts fall back to core pool values\\n */\\n bool isActive;\\n /**\\n * @notice Whether core pool risk factors can be used as fallback when the market\\n * is not configured in the specific pool, falls back when set to true\\n */\\n bool allowCorePoolFallback;\\n }\\n\\n /**\\n * @notice Tracks the selected pool for each user\\n * @dev\\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\\n * - A value of `0` represents the default core pool (legacy behavior)\\n */\\n mapping(address => uint96) public userPoolId;\\n\\n /**\\n * @notice Mapping of pool ID to its corresponding metadata and configuration\\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\\n * Not updated for the Core Pool (`poolId = 0`)\\n */\\n mapping(uint96 => PoolData) public pools;\\n\\n /**\\n * @notice Counter used to generate unique pool IDs\\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\\n */\\n uint96 public lastPoolId;\\n}\\n\\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\\n /// @notice Mapping of accounts authorized to execute flash loans\\n mapping(address => bool) public authorizedFlashLoan;\\n\\n /// @notice Whether flash loans are paused system-wide\\n bool public flashLoanPaused;\\n}\\n\\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\\n IDeviationBoundedOracle public deviationBoundedOracle;\\n}\\n\",\"keccak256\":\"0x436a83ad3f456a0dcfbdc1276086643b777f753345e05c4e0b68960e2911d496\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/Diamond.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IDiamondCut } from \\\"./interfaces/IDiamondCut.sol\\\";\\nimport { Unitroller } from \\\"../Unitroller.sol\\\";\\nimport { ComptrollerV19Storage } from \\\"../ComptrollerStorage.sol\\\";\\n\\n/**\\n * @title Diamond\\n * @author Venus\\n * @notice This contract contains functions related to facets\\n */\\ncontract Diamond is IDiamondCut, ComptrollerV19Storage {\\n /// @notice Emitted when functions are added, replaced or removed to facets\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut);\\n\\n struct Facet {\\n address facetAddress;\\n bytes4[] functionSelectors;\\n }\\n\\n /**\\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\\n * @param unitroller Address of the unitroller\\n */\\n function _become(Unitroller unitroller) public {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"not authorized\\\");\\n }\\n\\n /**\\n * @notice To add function selectors to the facet's mapping\\n * @dev Allows the contract admin to add function selectors\\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\\n */\\n function diamondCut(IDiamondCut.FacetCut[] memory diamondCut_) public {\\n require(msg.sender == admin, \\\"only unitroller admin can\\\");\\n libDiamondCut(diamondCut_);\\n }\\n\\n /**\\n * @notice Get all function selectors mapped to the facet address\\n * @param facet Address of the facet\\n * @return selectors Array of function selectors\\n */\\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\\n return _facetFunctionSelectors[facet].functionSelectors;\\n }\\n\\n /**\\n * @notice Get facet position in the _facetFunctionSelectors through facet address\\n * @param facet Address of the facet\\n * @return Position of the facet\\n */\\n function facetPosition(address facet) external view returns (uint256) {\\n return _facetFunctionSelectors[facet].facetAddressPosition;\\n }\\n\\n /**\\n * @notice Get all facet addresses\\n * @return facetAddresses Array of facet addresses\\n */\\n function facetAddresses() external view returns (address[] memory) {\\n return _facetAddresses;\\n }\\n\\n /**\\n * @notice Get facet address and position through function selector\\n * @param functionSelector function selector\\n * @return FacetAddressAndPosition facet address and position\\n */\\n function facetAddress(\\n bytes4 functionSelector\\n ) external view returns (ComptrollerV19Storage.FacetAddressAndPosition memory) {\\n return _selectorToFacetAndPosition[functionSelector];\\n }\\n\\n /**\\n * @notice Get all facets address and their function selector\\n * @return facets_ Array of Facet\\n */\\n function facets() external view returns (Facet[] memory) {\\n uint256 facetsLength = _facetAddresses.length;\\n Facet[] memory facets_ = new Facet[](facetsLength);\\n for (uint256 i; i < facetsLength; ++i) {\\n address facet = _facetAddresses[i];\\n facets_[i].facetAddress = facet;\\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\\n }\\n return facets_;\\n }\\n\\n /**\\n * @notice To add function selectors to the facets' mapping\\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\\n */\\n function libDiamondCut(IDiamondCut.FacetCut[] memory diamondCut_) internal {\\n uint256 diamondCutLength = diamondCut_.length;\\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\\n IDiamondCut.FacetCutAction action = diamondCut_[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(diamondCut_);\\n }\\n\\n /**\\n * @notice Add function selectors to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to add in the mapping\\n */\\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n require(functionSelectors.length != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n require(facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(facetAddress);\\n }\\n uint256 functionSelectorsLength = functionSelectors.length;\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(selector, selectorPosition, facetAddress);\\n ++selectorPosition;\\n }\\n }\\n\\n /**\\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to replace in the mapping\\n */\\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n require(functionSelectors.length != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n require(facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(facetAddress);\\n }\\n uint256 functionSelectorsLength = functionSelectors.length;\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(oldFacetAddress, selector);\\n addFunction(selector, selectorPosition, facetAddress);\\n ++selectorPosition;\\n }\\n }\\n\\n /**\\n * @notice Remove function selectors to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param functionSelectors Array of function selectors need to remove in the mapping\\n */\\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\\n uint256 functionSelectorsLength = functionSelectors.length;\\n require(functionSelectorsLength != 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n // if function does not exist then do nothing and revert\\n require(facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\\n bytes4 selector = functionSelectors[selectorIndex];\\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(oldFacetAddress, selector);\\n }\\n }\\n\\n /**\\n * @notice Add new facet to the proxy\\n * @param facetAddress Address of the facet\\n */\\n function addFacet(address facetAddress) internal {\\n enforceHasContractCode(facetAddress, \\\"Diamond: New facet has no code\\\");\\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\\n _facetAddresses.push(facetAddress);\\n }\\n\\n /**\\n * @notice Add function selector to the facet's address mapping\\n * @param selector funciton selector need to be added\\n * @param selectorPosition funciton selector position\\n * @param facetAddress Address of the facet\\n */\\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\\n }\\n\\n /**\\n * @notice Remove function selector to the facet's address mapping\\n * @param facetAddress Address of the facet\\n * @param selector function selectors need to remove in the mapping\\n */\\n function removeFunction(address facetAddress, bytes4 selector) internal {\\n require(facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\\n // if not the same then replace selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\\n delete _selectorToFacetAndPosition[selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n _facetAddresses.pop();\\n delete _facetFunctionSelectors[facetAddress];\\n }\\n }\\n\\n /**\\n * @dev Ensure that the given address has contract code deployed\\n * @param _contract The address to check for contract code\\n * @param _errorMessage The error message to display if the contract code is not deployed\\n */\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize != 0, _errorMessage);\\n }\\n\\n // Find facet for function that is called and execute the\\n // function if a facet is found and return any value.\\n fallback() external {\\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\\n require(facet != address(0), \\\"Diamond: Function does not exist\\\");\\n // Execute public function from facet using delegatecall and return any value.\\n assembly {\\n // copy function selector and any arguments\\n calldatacopy(0, 0, calldatasize())\\n // execute function call using the facet\\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\\n // get any return value\\n returndatacopy(0, 0, returndatasize())\\n // return any return value or error back to the caller\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x0517cc4bd5e654f8fa2084912a125bf7112122a896e1fc091f5351c4df89f4bb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n function diamondCut(FacetCut[] calldata _diamondCut) external;\\n}\\n\",\"keccak256\":\"0xcb93543c9122cf328715d2b242e99f8ca234bd1347d82290ad7a4e028f358141\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Unitroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { UnitrollerAdminStorage } from \\\"./ComptrollerStorage.sol\\\";\\nimport { ComptrollerErrorReporter } from \\\"../Utils/ErrorReporter.sol\\\";\\n\\n/**\\n * @title ComptrollerCore\\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\\n * VTokens should reference this contract as their comptroller.\\n */\\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint) {\\n // Check caller is pendingImplementation and pendingImplementation \\u2260 address(0)\\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = comptrollerImplementation;\\n address oldPendingImplementation = pendingComptrollerImplementation;\\n\\n comptrollerImplementation = pendingComptrollerImplementation;\\n\\n pendingComptrollerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, comptrollerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n fallback() external {\\n // delegate all other functions to current implementation\\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize())\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize())\\n }\\n default {\\n return(free_mem_ptr, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0x7e552ae197db0095044af62614b09426d3570bf15593aa7703be3a517287074b\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b5061203e8061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061030a575f3560e01c80638f738f361161019b578063c7ee005e116100e7578063e0f6123d116100a0578063e87554461161007a578063e875544614610931578063f445d7031461093a578063f851a44014610967578063fa6331d8146109795761030a565b8063e0f6123d146108c5578063e37d4b79146108e7578063e57e69c61461091e5761030a565b8063c7ee005e146107cb578063cdffacc6146107de578063d3270f9914610874578063d7c46d2d14610887578063dce154491461089f578063dcfbc0c7146108b25761030a565b8063adfca15e11610154578063bb82aa5e1161012e578063bb82aa5e1461077d578063bbb8864a14610790578063bec04f72146107af578063c5f956af146107b85761030a565b8063adfca15e146106ef578063b2eafc391461070f578063b8324c7c146107225761030a565b80638f738f36146106605780639254f5e51461068b57806394b2294b1461069e57806396c99064146106a75780639bb27d62146106c9578063a657e579146106dc5761030a565b80634a5844321161025a57806376551383116102135780637dc0d1d0116101ed5780637dc0d1d0146105ff5780637fb8e8cd146106125780638a7dc1651461061f5780638c1ac18a1461063e5761030a565b806376551383146105c55780637a0ed627146105d75780637d172bd5146105ec5761030a565b80634a5844321461051657806352d84d1e1461053557806352ef6b2c146105485780635dd3fc9d1461055d578063719f701b1461057c57806373769099146105855761030a565b806321af4569116102c75780632bc7e29e116102a15780632bc7e29e146104ad5780634088c73e146104cc57806341a18d2c146104d9578063425fad58146105035761030a565b806321af45691461045c57806324a3d62214610487578063267822471461049a5761030a565b806302c3bcbb1461039e57806304ef9d58146103d057806308e0225c146103d95780630db4b4e51461040357806310b983381461040c5780631d504dc614610449575b5f80356001600160e01b0319168152602e60205260409020546001600160a01b03168061037e5760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b365f80375f80365f845af43d5f803e808015610398573d5ff35b3d5ffd5b005b6103bd6103ac36600461196c565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103bd60225481565b6103bd6103e736600461198e565b601360209081525f928352604080842090915290825290205481565b6103bd601d5481565b61043961041a36600461198e565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103c7565b61039c61045736600461196c565b610982565b601e5461046f906001600160a01b031681565b6040516001600160a01b0390911681526020016103c7565b600a5461046f906001600160a01b031681565b60015461046f906001600160a01b031681565b6103bd6104bb36600461196c565b60166020525f908152604090205481565b6018546104399060ff1681565b6103bd6104e736600461198e565b601260209081525f928352604080842090915290825290205481565b6018546104399062010000900460ff1681565b6103bd61052436600461196c565b601f6020525f908152604090205481565b61046f6105433660046119c5565b610ae0565b610550610b08565b6040516103c791906119dc565b6103bd61056b36600461196c565b602b6020525f908152604090205481565b6103bd601c5481565b6105ad61059336600461196c565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103c7565b60185461043990610100900460ff1681565b6105df610b68565b6040516103c79190611a6c565b601b5461046f906001600160a01b031681565b60045461046f906001600160a01b031681565b6039546104399060ff1681565b6103bd61062d36600461196c565b60146020525f908152604090205481565b61043961064c36600461196c565b602d6020525f908152604090205460ff1681565b6103bd61066e36600461196c565b6001600160a01b03165f908152602f602052604090206001015490565b60155461046f906001600160a01b031681565b6103bd60075481565b6106ba6106b5366004611ae9565b610cec565b6040516103c793929190611b3d565b60255461046f906001600160a01b031681565b6037546105ad906001600160601b031681565b6107026106fd36600461196c565b610d99565b6040516103c79190611b66565b60205461046f906001600160a01b031681565b61075961073036600461196c565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103c7565b60025461046f906001600160a01b031681565b6103bd61079e36600461196c565b602a6020525f908152604090205481565b6103bd60175481565b60215461046f906001600160a01b031681565b60315461046f906001600160a01b031681565b6108476107ec366004611b94565b604080518082019091525f8082526020820152506001600160e01b0319165f908152602e60209081526040918290208251808401909352546001600160a01b0381168352600160a01b90046001600160601b03169082015290565b6040805182516001600160a01b031681526020928301516001600160601b031692810192909252016103c7565b60265461046f906001600160a01b031681565b60395461046f9061010090046001600160a01b031681565b61046f6108ad366004611bad565b610e2e565b60035461046f906001600160a01b031681565b6104396108d336600461196c565b60386020525f908152604090205460ff1681565b6107596108f536600461196c565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61039c61092c366004611c68565b610e62565b6103bd60055481565b61043961094836600461198e565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461046f906001600160a01b031681565b6103bd601a5481565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e29190611dce565b6001600160a01b0316336001600160a01b031614610a3e5760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b6044820152606401610375565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a9f9190611de9565b15610add5760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b6044820152606401610375565b50565b600d8181548110610aef575f80fd5b5f918252602090912001546001600160a01b0316905081565b60606030805480602002602001604051908101604052809291908181526020018280548015610b5e57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610b40575b5050505050905090565b6030546060905f8167ffffffffffffffff811115610b8857610b88611bd7565b604051908082528060200260200182016040528015610bcd57816020015b604080518082019091525f815260606020820152815260200190600190039081610ba65790505b5090505f5b82811015610ce5575f60308281548110610bee57610bee611e00565b905f5260205f20015f9054906101000a90046001600160a01b0316905080838381518110610c1e57610c1e611e00565b6020908102919091018101516001600160a01b0392831690529082165f908152602f825260409081902080548251818502810185019093528083529192909190830182828015610cb757602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610c795790505b5050505050838381518110610cce57610cce611e00565b602090810291909101810151015250600101610bd2565b5092915050565b60366020525f9081526040902080548190610d0690611e14565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3290611e14565b8015610d7d5780601f10610d5457610100808354040283529160200191610d7d565b820191905f5260205f20905b815481529060010190602001808311610d6057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6001600160a01b0381165f908152602f6020908152604091829020805483518184028101840190945280845260609392830182828015610e2257602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610de45790505b50505050509050919050565b6008602052815f5260405f208181548110610e47575f80fd5b5f918252602090912001546001600160a01b03169150829050565b5f546001600160a01b03163314610eb75760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b6044820152606401610375565b610add8180515f5b81811015611072575f838281518110610eda57610eda611e00565b60200260200101516020015190505f6002811115610efa57610efa611e4c565b816002811115610f0c57610f0c611e4c565b03610f5957610f54848381518110610f2657610f26611e00565b60200260200101515f0151858481518110610f4357610f43611e00565b6020026020010151604001516110ae565b611069565b6001816002811115610f6d57610f6d611e4c565b03610fb557610f54848381518110610f8757610f87611e00565b60200260200101515f0151858481518110610fa457610fa4611e00565b60200260200101516040015161120d565b6002816002811115610fc957610fc9611e4c565b0361101157610f54848381518110610fe357610fe3611e00565b60200260200101515f015185848151811061100057611000611e00565b60200260200101516040015161137c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401610375565b50600101610ebf565b507f2e97860c6f47eab0292d51fa3ceec7e373c62af1e7eb2a28ae82998b80de6cfd826040516110a29190611e60565b60405180910390a15050565b80515f036110ce5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b0382166110f45760405162461bcd60e51b815260040161037590611f44565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611126576111268361147d565b81515f5b81811015611206575f84828151811061114557611145611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031680156111e35760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b6064820152608401610375565b6111ee82868961151f565b6111f785611fa4565b9450505080600101905061112a565b5050505050565b80515f0361122d5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b0382166112535760405162461bcd60e51b815260040161037590611f44565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611285576112858361147d565b81515f5b81811015611206575f8482815181106112a4576112a4611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b03908116908716810361134f5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610375565b61135981836115bd565b61136482868961151f565b61136d85611fa4565b94505050806001019050611289565b80515f81900361139e5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b038316156114145760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b6064820152608401610375565b5f5b81811015611477575f83828151811061143157611431611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031661146d81836115bd565b5050600101611416565b50505050565b6114bc816040518060400160405280601e81526020017f4469616d6f6e643a204e657720666163657420686173206e6f20636f64650000815250611902565b603080546001600160a01b039092165f818152602f60205260408120600190810185905584018355919091527f6ff97a59c90d62cc7236ba3a37cd85351bf564556780cf8c1157a220f31f0cbb90910180546001600160a01b0319169091179055565b6001600160e01b031983165f818152602e6020818152604080842080546001600160601b03909816600160a01b026001600160a01b0398891617815595909616808452602f825295832080546001810182559084528184206008820401805460e09990991c60046007909316929092026101000a91820263ffffffff909202199098161790965591905290925281546001600160a01b031916179055565b6001600160a01b0382166116395760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610375565b6001600160e01b031981165f908152602e60209081526040808320546001600160a01b0386168452602f909252822054600160a01b9091046001600160601b0316919061168890600190611fc9565b9050808214611774576001600160a01b0384165f908152602f602052604081208054839081106116ba576116ba611e00565b5f91825260208083206008830401546001600160a01b0389168452602f9091526040909220805460079092166004026101000a90920460e01b92508291908590811061170857611708611e00565b5f91825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b0319929092168252602e90526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384165f908152602f6020526040902080548061179a5761179a611fe2565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252602e905260408120819055819003611477576030545f906117f990600190611fc9565b6001600160a01b0386165f908152602f602052604090206001015490915080821461189d575f6030838154811061183257611832611e00565b5f91825260209091200154603080546001600160a01b03909216925082918490811061186057611860611e00565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152602f909152604090206001018190555b60308054806118ae576118ae611fe2565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092556001600160a01b0388168252602f905260408120906118f18282611923565b600182015f90555050505050505050565b813b81816114775760405162461bcd60e51b81526004016103759190611ff6565b5080545f825560070160089004905f5260205f2090810190610add91905b80821115611954575f8155600101611941565b5090565b6001600160a01b0381168114610add575f80fd5b5f6020828403121561197c575f80fd5b813561198781611958565b9392505050565b5f806040838503121561199f575f80fd5b82356119aa81611958565b915060208301356119ba81611958565b809150509250929050565b5f602082840312156119d5575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b81811015611a1c5783516001600160a01b0316835292840192918401916001016119f7565b50909695505050505050565b5f815180845260208085019450602084015f5b83811015611a615781516001600160e01b03191687529582019590820190600101611a3b565b509495945050505050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611adb57888303603f19018552815180516001600160a01b03168452870151878401879052611ac887850182611a28565b9588019593505090860190600101611a93565b509098975050505050505050565b5f60208284031215611af9575f80fd5b81356001600160601b0381168114611987575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f611b4f6060830186611b0f565b931515602083015250901515604090910152919050565b602081525f6119876020830184611a28565b80356001600160e01b031981168114611b8f575f80fd5b919050565b5f60208284031215611ba4575f80fd5b61198782611b78565b5f8060408385031215611bbe575f80fd5b8235611bc981611958565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611c0e57611c0e611bd7565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c3d57611c3d611bd7565b604052919050565b5f67ffffffffffffffff821115611c5e57611c5e611bd7565b5060051b60200190565b5f6020808385031215611c79575f80fd5b823567ffffffffffffffff80821115611c90575f80fd5b818501915085601f830112611ca3575f80fd5b8135611cb6611cb182611c45565b611c14565b81815260059190911b83018401908481019088831115611cd4575f80fd5b8585015b83811015611dc157803585811115611cee575f80fd5b86016060818c03601f1901811315611d04575f80fd5b611d0c611beb565b89830135611d1981611958565b815260408381013560038110611d2d575f80fd5b828c0152918301359188831115611d42575f80fd5b82840193508d603f850112611d55575f80fd5b8a8401359250611d67611cb184611c45565b83815260059390931b84018101928b8101908f851115611d85575f80fd5b948201945b84861015611daa57611d9b86611b78565b8252948c0194908c0190611d8a565b918301919091525085525050918601918601611cd8565b5098975050505050505050565b5f60208284031215611dde575f80fd5b815161198781611958565b5f60208284031215611df9575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680611e2857607f821691505b602082108103611e4657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611adb57888303603f19018552815180516001600160a01b031684528781015160609060038110611eca57634e487b7160e01b5f52602160045260245ffd5b858a01529087015187850182905290611ee581860183611a28565b968901969450505090860190600101611e87565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160601b03808316818103611fbf57611fbf611f90565b6001019392505050565b81810381811115611fdc57611fdc611f90565b92915050565b634e487b7160e01b5f52603160045260245ffd5b602081525f6119876020830184611b0f56fea26469706673582212209b317f11a3f70d4e9ca7f34009f4db2c0f6193dc12db861247c020a43dd4f1d564736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061030a575f3560e01c80638f738f361161019b578063c7ee005e116100e7578063e0f6123d116100a0578063e87554461161007a578063e875544614610931578063f445d7031461093a578063f851a44014610967578063fa6331d8146109795761030a565b8063e0f6123d146108c5578063e37d4b79146108e7578063e57e69c61461091e5761030a565b8063c7ee005e146107cb578063cdffacc6146107de578063d3270f9914610874578063d7c46d2d14610887578063dce154491461089f578063dcfbc0c7146108b25761030a565b8063adfca15e11610154578063bb82aa5e1161012e578063bb82aa5e1461077d578063bbb8864a14610790578063bec04f72146107af578063c5f956af146107b85761030a565b8063adfca15e146106ef578063b2eafc391461070f578063b8324c7c146107225761030a565b80638f738f36146106605780639254f5e51461068b57806394b2294b1461069e57806396c99064146106a75780639bb27d62146106c9578063a657e579146106dc5761030a565b80634a5844321161025a57806376551383116102135780637dc0d1d0116101ed5780637dc0d1d0146105ff5780637fb8e8cd146106125780638a7dc1651461061f5780638c1ac18a1461063e5761030a565b806376551383146105c55780637a0ed627146105d75780637d172bd5146105ec5761030a565b80634a5844321461051657806352d84d1e1461053557806352ef6b2c146105485780635dd3fc9d1461055d578063719f701b1461057c57806373769099146105855761030a565b806321af4569116102c75780632bc7e29e116102a15780632bc7e29e146104ad5780634088c73e146104cc57806341a18d2c146104d9578063425fad58146105035761030a565b806321af45691461045c57806324a3d62214610487578063267822471461049a5761030a565b806302c3bcbb1461039e57806304ef9d58146103d057806308e0225c146103d95780630db4b4e51461040357806310b983381461040c5780631d504dc614610449575b5f80356001600160e01b0319168152602e60205260409020546001600160a01b03168061037e5760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b365f80375f80365f845af43d5f803e808015610398573d5ff35b3d5ffd5b005b6103bd6103ac36600461196c565b60276020525f908152604090205481565b6040519081526020015b60405180910390f35b6103bd60225481565b6103bd6103e736600461198e565b601360209081525f928352604080842090915290825290205481565b6103bd601d5481565b61043961041a36600461198e565b602c60209081525f928352604080842090915290825290205460ff1681565b60405190151581526020016103c7565b61039c61045736600461196c565b610982565b601e5461046f906001600160a01b031681565b6040516001600160a01b0390911681526020016103c7565b600a5461046f906001600160a01b031681565b60015461046f906001600160a01b031681565b6103bd6104bb36600461196c565b60166020525f908152604090205481565b6018546104399060ff1681565b6103bd6104e736600461198e565b601260209081525f928352604080842090915290825290205481565b6018546104399062010000900460ff1681565b6103bd61052436600461196c565b601f6020525f908152604090205481565b61046f6105433660046119c5565b610ae0565b610550610b08565b6040516103c791906119dc565b6103bd61056b36600461196c565b602b6020525f908152604090205481565b6103bd601c5481565b6105ad61059336600461196c565b60356020525f90815260409020546001600160601b031681565b6040516001600160601b0390911681526020016103c7565b60185461043990610100900460ff1681565b6105df610b68565b6040516103c79190611a6c565b601b5461046f906001600160a01b031681565b60045461046f906001600160a01b031681565b6039546104399060ff1681565b6103bd61062d36600461196c565b60146020525f908152604090205481565b61043961064c36600461196c565b602d6020525f908152604090205460ff1681565b6103bd61066e36600461196c565b6001600160a01b03165f908152602f602052604090206001015490565b60155461046f906001600160a01b031681565b6103bd60075481565b6106ba6106b5366004611ae9565b610cec565b6040516103c793929190611b3d565b60255461046f906001600160a01b031681565b6037546105ad906001600160601b031681565b6107026106fd36600461196c565b610d99565b6040516103c79190611b66565b60205461046f906001600160a01b031681565b61075961073036600461196c565b60106020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016103c7565b60025461046f906001600160a01b031681565b6103bd61079e36600461196c565b602a6020525f908152604090205481565b6103bd60175481565b60215461046f906001600160a01b031681565b60315461046f906001600160a01b031681565b6108476107ec366004611b94565b604080518082019091525f8082526020820152506001600160e01b0319165f908152602e60209081526040918290208251808401909352546001600160a01b0381168352600160a01b90046001600160601b03169082015290565b6040805182516001600160a01b031681526020928301516001600160601b031692810192909252016103c7565b60265461046f906001600160a01b031681565b60395461046f9061010090046001600160a01b031681565b61046f6108ad366004611bad565b610e2e565b60035461046f906001600160a01b031681565b6104396108d336600461196c565b60386020525f908152604090205460ff1681565b6107596108f536600461196c565b60116020525f90815260409020546001600160e01b03811690600160e01b900463ffffffff1682565b61039c61092c366004611c68565b610e62565b6103bd60055481565b61043961094836600461198e565b603260209081525f928352604080842090915290825290205460ff1681565b5f5461046f906001600160a01b031681565b6103bd601a5481565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109be573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109e29190611dce565b6001600160a01b0316336001600160a01b031614610a3e5760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b6044820152606401610375565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610a7b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a9f9190611de9565b15610add5760405162461bcd60e51b815260206004820152600e60248201526d1b9bdd08185d5d1a1bdc9a5e995960921b6044820152606401610375565b50565b600d8181548110610aef575f80fd5b5f918252602090912001546001600160a01b0316905081565b60606030805480602002602001604051908101604052809291908181526020018280548015610b5e57602002820191905f5260205f20905b81546001600160a01b03168152600190910190602001808311610b40575b5050505050905090565b6030546060905f8167ffffffffffffffff811115610b8857610b88611bd7565b604051908082528060200260200182016040528015610bcd57816020015b604080518082019091525f815260606020820152815260200190600190039081610ba65790505b5090505f5b82811015610ce5575f60308281548110610bee57610bee611e00565b905f5260205f20015f9054906101000a90046001600160a01b0316905080838381518110610c1e57610c1e611e00565b6020908102919091018101516001600160a01b0392831690529082165f908152602f825260409081902080548251818502810185019093528083529192909190830182828015610cb757602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610c795790505b5050505050838381518110610cce57610cce611e00565b602090810291909101810151015250600101610bd2565b5092915050565b60366020525f9081526040902080548190610d0690611e14565b80601f0160208091040260200160405190810160405280929190818152602001828054610d3290611e14565b8015610d7d5780601f10610d5457610100808354040283529160200191610d7d565b820191905f5260205f20905b815481529060010190602001808311610d6057829003601f168201915b5050506002909301549192505060ff8082169161010090041683565b6001600160a01b0381165f908152602f6020908152604091829020805483518184028101840190945280845260609392830182828015610e2257602002820191905f5260205f20905f905b82829054906101000a900460e01b6001600160e01b03191681526020019060040190602082600301049283019260010382029150808411610de45790505b50505050509050919050565b6008602052815f5260405f208181548110610e47575f80fd5b5f918252602090912001546001600160a01b03169150829050565b5f546001600160a01b03163314610eb75760405162461bcd60e51b815260206004820152601960248201527837b7363c903ab734ba3937b63632b91030b236b4b71031b0b760391b6044820152606401610375565b610add8180515f5b81811015611072575f838281518110610eda57610eda611e00565b60200260200101516020015190505f6002811115610efa57610efa611e4c565b816002811115610f0c57610f0c611e4c565b03610f5957610f54848381518110610f2657610f26611e00565b60200260200101515f0151858481518110610f4357610f43611e00565b6020026020010151604001516110ae565b611069565b6001816002811115610f6d57610f6d611e4c565b03610fb557610f54848381518110610f8757610f87611e00565b60200260200101515f0151858481518110610fa457610fa4611e00565b60200260200101516040015161120d565b6002816002811115610fc957610fc9611e4c565b0361101157610f54848381518110610fe357610fe3611e00565b60200260200101515f015185848151811061100057611000611e00565b60200260200101516040015161137c565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401610375565b50600101610ebf565b507f2e97860c6f47eab0292d51fa3ceec7e373c62af1e7eb2a28ae82998b80de6cfd826040516110a29190611e60565b60405180910390a15050565b80515f036110ce5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b0382166110f45760405162461bcd60e51b815260040161037590611f44565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611126576111268361147d565b81515f5b81811015611206575f84828151811061114557611145611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031680156111e35760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b6064820152608401610375565b6111ee82868961151f565b6111f785611fa4565b9450505080600101905061112a565b5050505050565b80515f0361122d5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b0382166112535760405162461bcd60e51b815260040161037590611f44565b6001600160a01b0382165f908152602f6020526040812054906001600160601b0382169003611285576112858361147d565b81515f5b81811015611206575f8482815181106112a4576112a4611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b03908116908716810361134f5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610375565b61135981836115bd565b61136482868961151f565b61136d85611fa4565b94505050806001019050611289565b80515f81900361139e5760405162461bcd60e51b815260040161037590611ef9565b6001600160a01b038316156114145760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b6064820152608401610375565b5f5b81811015611477575f83828151811061143157611431611e00565b6020908102919091018101516001600160e01b031981165f908152602e9092526040909120549091506001600160a01b031661146d81836115bd565b5050600101611416565b50505050565b6114bc816040518060400160405280601e81526020017f4469616d6f6e643a204e657720666163657420686173206e6f20636f64650000815250611902565b603080546001600160a01b039092165f818152602f60205260408120600190810185905584018355919091527f6ff97a59c90d62cc7236ba3a37cd85351bf564556780cf8c1157a220f31f0cbb90910180546001600160a01b0319169091179055565b6001600160e01b031983165f818152602e6020818152604080842080546001600160601b03909816600160a01b026001600160a01b0398891617815595909616808452602f825295832080546001810182559084528184206008820401805460e09990991c60046007909316929092026101000a91820263ffffffff909202199098161790965591905290925281546001600160a01b031916179055565b6001600160a01b0382166116395760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610375565b6001600160e01b031981165f908152602e60209081526040808320546001600160a01b0386168452602f909252822054600160a01b9091046001600160601b0316919061168890600190611fc9565b9050808214611774576001600160a01b0384165f908152602f602052604081208054839081106116ba576116ba611e00565b5f91825260208083206008830401546001600160a01b0389168452602f9091526040909220805460079092166004026101000a90920460e01b92508291908590811061170857611708611e00565b5f91825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790556001600160e01b0319929092168252602e90526040902080546001600160a01b0316600160a01b6001600160601b038516021790555b6001600160a01b0384165f908152602f6020526040902080548061179a5761179a611fe2565b5f828152602080822060085f1990940193840401805463ffffffff600460078716026101000a0219169055919092556001600160e01b031985168252602e905260408120819055819003611477576030545f906117f990600190611fc9565b6001600160a01b0386165f908152602f602052604090206001015490915080821461189d575f6030838154811061183257611832611e00565b5f91825260209091200154603080546001600160a01b03909216925082918490811061186057611860611e00565b5f91825260208083209190910180546001600160a01b0319166001600160a01b03948516179055929091168152602f909152604090206001018190555b60308054806118ae576118ae611fe2565b5f828152602080822083015f1990810180546001600160a01b03191690559092019092556001600160a01b0388168252602f905260408120906118f18282611923565b600182015f90555050505050505050565b813b81816114775760405162461bcd60e51b81526004016103759190611ff6565b5080545f825560070160089004905f5260205f2090810190610add91905b80821115611954575f8155600101611941565b5090565b6001600160a01b0381168114610add575f80fd5b5f6020828403121561197c575f80fd5b813561198781611958565b9392505050565b5f806040838503121561199f575f80fd5b82356119aa81611958565b915060208301356119ba81611958565b809150509250929050565b5f602082840312156119d5575f80fd5b5035919050565b602080825282518282018190525f9190848201906040850190845b81811015611a1c5783516001600160a01b0316835292840192918401916001016119f7565b50909695505050505050565b5f815180845260208085019450602084015f5b83811015611a615781516001600160e01b03191687529582019590820190600101611a3b565b509495945050505050565b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611adb57888303603f19018552815180516001600160a01b03168452870151878401879052611ac887850182611a28565b9588019593505090860190600101611a93565b509098975050505050505050565b5f60208284031215611af9575f80fd5b81356001600160601b0381168114611987575f80fd5b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b606081525f611b4f6060830186611b0f565b931515602083015250901515604090910152919050565b602081525f6119876020830184611a28565b80356001600160e01b031981168114611b8f575f80fd5b919050565b5f60208284031215611ba4575f80fd5b61198782611b78565b5f8060408385031215611bbe575f80fd5b8235611bc981611958565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b6040516060810167ffffffffffffffff81118282101715611c0e57611c0e611bd7565b60405290565b604051601f8201601f1916810167ffffffffffffffff81118282101715611c3d57611c3d611bd7565b604052919050565b5f67ffffffffffffffff821115611c5e57611c5e611bd7565b5060051b60200190565b5f6020808385031215611c79575f80fd5b823567ffffffffffffffff80821115611c90575f80fd5b818501915085601f830112611ca3575f80fd5b8135611cb6611cb182611c45565b611c14565b81815260059190911b83018401908481019088831115611cd4575f80fd5b8585015b83811015611dc157803585811115611cee575f80fd5b86016060818c03601f1901811315611d04575f80fd5b611d0c611beb565b89830135611d1981611958565b815260408381013560038110611d2d575f80fd5b828c0152918301359188831115611d42575f80fd5b82840193508d603f850112611d55575f80fd5b8a8401359250611d67611cb184611c45565b83815260059390931b84018101928b8101908f851115611d85575f80fd5b948201945b84861015611daa57611d9b86611b78565b8252948c0194908c0190611d8a565b918301919091525085525050918601918601611cd8565b5098975050505050505050565b5f60208284031215611dde575f80fd5b815161198781611958565b5f60208284031215611df9575f80fd5b5051919050565b634e487b7160e01b5f52603260045260245ffd5b600181811c90821680611e2857607f821691505b602082108103611e4657634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52602160045260245ffd5b5f60208083018184528085518083526040925060408601915060408160051b8701018488015f5b83811015611adb57888303603f19018552815180516001600160a01b031684528781015160609060038110611eca57634e487b7160e01b5f52602160045260245ffd5b858a01529087015187850182905290611ee581860183611a28565b968901969450505090860190600101611e87565b6020808252602b908201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660408201526a1858d95d081d1bc818dd5d60aa1b606082015260800190565b6020808252602c908201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260408201526b65206164647265737328302960a01b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160601b03808316818103611fbf57611fbf611f90565b6001019392505050565b81810381811115611fdc57611fdc611f90565b92915050565b634e487b7160e01b5f52603160045260245ffd5b602081525f6119876020830184611b0f56fea26469706673582212209b317f11a3f70d4e9ca7f34009f4db2c0f6193dc12db861247c020a43dd4f1d564736f6c63430008190033", "devdoc": { "author": "Venus", "kind": "dev", @@ -1024,6 +1037,9 @@ "comptrollerImplementation()": { "notice": "Active brains of Unitroller" }, + "deviationBoundedOracle()": { + "notice": "DeviationBoundedOracle for conservative pricing in CF path" + }, "diamondCut((address,uint8,bytes4[])[])": { "notice": "To add function selectors to the facet's mapping" }, @@ -1136,7 +1152,7 @@ "storageLayout": { "storage": [ { - "astId": 1677, + "astId": 9780, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "admin", "offset": 0, @@ -1144,7 +1160,7 @@ "type": "t_address" }, { - "astId": 1680, + "astId": 9783, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "pendingAdmin", "offset": 0, @@ -1152,7 +1168,7 @@ "type": "t_address" }, { - "astId": 1683, + "astId": 9786, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "comptrollerImplementation", "offset": 0, @@ -1160,7 +1176,7 @@ "type": "t_address" }, { - "astId": 1686, + "astId": 9789, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "pendingComptrollerImplementation", "offset": 0, @@ -1168,15 +1184,15 @@ "type": "t_address" }, { - "astId": 1693, + "astId": 9796, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "oracle", "offset": 0, "slot": "4", - "type": "t_contract(ResilientOracleInterface)992" + "type": "t_contract(ResilientOracleInterface)8467" }, { - "astId": 1696, + "astId": 9799, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "closeFactorMantissa", "offset": 0, @@ -1184,7 +1200,7 @@ "type": "t_uint256" }, { - "astId": 1699, + "astId": 9802, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_oldLiquidationIncentiveMantissa", "offset": 0, @@ -1192,7 +1208,7 @@ "type": "t_uint256" }, { - "astId": 1702, + "astId": 9805, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "maxAssets", "offset": 0, @@ -1200,23 +1216,23 @@ "type": "t_uint256" }, { - "astId": 1709, + "astId": 9812, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "accountAssets", "offset": 0, "slot": "8", - "type": "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)" + "type": "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)" }, { - "astId": 1743, + "astId": 9846, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_poolMarkets", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)" + "type": "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)" }, { - "astId": 1746, + "astId": 9849, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "pauseGuardian", "offset": 0, @@ -1224,7 +1240,7 @@ "type": "t_address" }, { - "astId": 1749, + "astId": 9852, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_mintGuardianPaused", "offset": 20, @@ -1232,7 +1248,7 @@ "type": "t_bool" }, { - "astId": 1752, + "astId": 9855, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_borrowGuardianPaused", "offset": 21, @@ -1240,7 +1256,7 @@ "type": "t_bool" }, { - "astId": 1755, + "astId": 9858, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "transferGuardianPaused", "offset": 22, @@ -1248,7 +1264,7 @@ "type": "t_bool" }, { - "astId": 1758, + "astId": 9861, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "seizeGuardianPaused", "offset": 23, @@ -1256,7 +1272,7 @@ "type": "t_bool" }, { - "astId": 1763, + "astId": 9866, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "mintGuardianPaused", "offset": 0, @@ -1264,7 +1280,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1768, + "astId": 9871, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "borrowGuardianPaused", "offset": 0, @@ -1272,15 +1288,15 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1780, + "astId": 9883, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "allMarkets", "offset": 0, "slot": "13", - "type": "t_array(t_contract(VToken)32634)dyn_storage" + "type": "t_array(t_contract(VToken)58633)dyn_storage" }, { - "astId": 1783, + "astId": 9886, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusRate", "offset": 0, @@ -1288,7 +1304,7 @@ "type": "t_uint256" }, { - "astId": 1788, + "astId": 9891, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusSpeeds", "offset": 0, @@ -1296,23 +1312,23 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1794, + "astId": 9897, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusSupplyState", "offset": 0, "slot": "16", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1800, + "astId": 9903, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusBorrowState", "offset": 0, "slot": "17", - "type": "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)" + "type": "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)" }, { - "astId": 1807, + "astId": 9910, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusSupplierIndex", "offset": 0, @@ -1320,7 +1336,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1814, + "astId": 9917, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusBorrowerIndex", "offset": 0, @@ -1328,7 +1344,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" }, { - "astId": 1819, + "astId": 9922, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusAccrued", "offset": 0, @@ -1336,15 +1352,15 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1823, + "astId": 9926, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "vaiController", "offset": 0, "slot": "21", - "type": "t_contract(VAIControllerInterface)25733" + "type": "t_contract(VAIControllerInterface)51683" }, { - "astId": 1828, + "astId": 9931, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "mintedVAIs", "offset": 0, @@ -1352,7 +1368,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1831, + "astId": 9934, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "vaiMintRate", "offset": 0, @@ -1360,7 +1376,7 @@ "type": "t_uint256" }, { - "astId": 1834, + "astId": 9937, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "mintVAIGuardianPaused", "offset": 0, @@ -1368,7 +1384,7 @@ "type": "t_bool" }, { - "astId": 1836, + "astId": 9939, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "repayVAIGuardianPaused", "offset": 1, @@ -1376,7 +1392,7 @@ "type": "t_bool" }, { - "astId": 1839, + "astId": 9942, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "protocolPaused", "offset": 2, @@ -1384,7 +1400,7 @@ "type": "t_bool" }, { - "astId": 1842, + "astId": 9945, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusVAIRate", "offset": 0, @@ -1392,7 +1408,7 @@ "type": "t_uint256" }, { - "astId": 1848, + "astId": 9951, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusVAIVaultRate", "offset": 0, @@ -1400,7 +1416,7 @@ "type": "t_uint256" }, { - "astId": 1850, + "astId": 9953, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "vaiVaultAddress", "offset": 0, @@ -1408,7 +1424,7 @@ "type": "t_address" }, { - "astId": 1852, + "astId": 9955, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "releaseStartBlock", "offset": 0, @@ -1416,7 +1432,7 @@ "type": "t_uint256" }, { - "astId": 1854, + "astId": 9957, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "minReleaseAmount", "offset": 0, @@ -1424,7 +1440,7 @@ "type": "t_uint256" }, { - "astId": 1860, + "astId": 9963, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "borrowCapGuardian", "offset": 0, @@ -1432,7 +1448,7 @@ "type": "t_address" }, { - "astId": 1865, + "astId": 9968, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "borrowCaps", "offset": 0, @@ -1440,7 +1456,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1871, + "astId": 9974, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "treasuryGuardian", "offset": 0, @@ -1448,7 +1464,7 @@ "type": "t_address" }, { - "astId": 1874, + "astId": 9977, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "treasuryAddress", "offset": 0, @@ -1456,7 +1472,7 @@ "type": "t_address" }, { - "astId": 1877, + "astId": 9980, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "treasuryPercent", "offset": 0, @@ -1464,7 +1480,7 @@ "type": "t_uint256" }, { - "astId": 1885, + "astId": 9988, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusContributorSpeeds", "offset": 0, @@ -1472,7 +1488,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1890, + "astId": 9993, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "lastContributorBlock", "offset": 0, @@ -1480,7 +1496,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1895, + "astId": 9998, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "liquidatorContract", "offset": 0, @@ -1488,15 +1504,15 @@ "type": "t_address" }, { - "astId": 1901, + "astId": 10004, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "comptrollerLens", "offset": 0, "slot": "38", - "type": "t_contract(ComptrollerLensInterface)1660" + "type": "t_contract(ComptrollerLensInterface)9761" }, { - "astId": 1909, + "astId": 10012, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "supplyCaps", "offset": 0, @@ -1504,7 +1520,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1915, + "astId": 10018, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "accessControl", "offset": 0, @@ -1512,7 +1528,7 @@ "type": "t_address" }, { - "astId": 1922, + "astId": 10025, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_actionPaused", "offset": 0, @@ -1520,7 +1536,7 @@ "type": "t_mapping(t_address,t_mapping(t_uint256,t_bool))" }, { - "astId": 1930, + "astId": 10033, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusBorrowSpeeds", "offset": 0, @@ -1528,7 +1544,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1935, + "astId": 10038, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "venusSupplySpeeds", "offset": 0, @@ -1536,7 +1552,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 1945, + "astId": 10048, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "approvedDelegates", "offset": 0, @@ -1544,7 +1560,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 1953, + "astId": 10056, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isForcedLiquidationEnabled", "offset": 0, @@ -1552,23 +1568,23 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1972, + "astId": 10075, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_selectorToFacetAndPosition", "offset": 0, "slot": "46", - "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)" + "type": "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)" }, { - "astId": 1977, + "astId": 10080, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_facetFunctionSelectors", "offset": 0, "slot": "47", - "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)" + "type": "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)" }, { - "astId": 1980, + "astId": 10083, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "_facetAddresses", "offset": 0, @@ -1576,15 +1592,15 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 1987, + "astId": 10090, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "prime", "offset": 0, "slot": "49", - "type": "t_contract(IPrime)22911" + "type": "t_contract(IPrime)42902" }, { - "astId": 1997, + "astId": 10100, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isForcedLiquidationEnabledForUser", "offset": 0, @@ -1592,7 +1608,7 @@ "type": "t_mapping(t_address,t_mapping(t_address,t_bool))" }, { - "astId": 2003, + "astId": 10106, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "xvs", "offset": 0, @@ -1600,7 +1616,7 @@ "type": "t_address" }, { - "astId": 2006, + "astId": 10109, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "xvsVToken", "offset": 0, @@ -1608,7 +1624,7 @@ "type": "t_address" }, { - "astId": 2028, + "astId": 10131, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "userPoolId", "offset": 0, @@ -1616,15 +1632,15 @@ "type": "t_mapping(t_address,t_uint96)" }, { - "astId": 2034, + "astId": 10137, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "pools", "offset": 0, "slot": "54", - "type": "t_mapping(t_uint96,t_struct(PoolData)2023_storage)" + "type": "t_mapping(t_uint96,t_struct(PoolData)10126_storage)" }, { - "astId": 2037, + "astId": 10140, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "lastPoolId", "offset": 0, @@ -1632,7 +1648,7 @@ "type": "t_uint96" }, { - "astId": 2045, + "astId": 10148, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "authorizedFlashLoan", "offset": 0, @@ -1640,12 +1656,20 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 2048, + "astId": 10151, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "flashLoanPaused", "offset": 0, "slot": "57", "type": "t_bool" + }, + { + "astId": 10158, + "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", + "label": "deviationBoundedOracle", + "offset": 1, + "slot": "57", + "type": "t_contract(IDeviationBoundedOracle)8437" } ], "types": { @@ -1666,8 +1690,8 @@ "label": "bytes4[]", "numberOfBytes": "32" }, - "t_array(t_contract(VToken)32634)dyn_storage": { - "base": "t_contract(VToken)32634", + "t_array(t_contract(VToken)58633)dyn_storage": { + "base": "t_contract(VToken)58633", "encoding": "dynamic_array", "label": "contract VToken[]", "numberOfBytes": "32" @@ -1682,37 +1706,42 @@ "label": "bytes4", "numberOfBytes": "4" }, - "t_contract(ComptrollerLensInterface)1660": { + "t_contract(ComptrollerLensInterface)9761": { "encoding": "inplace", "label": "contract ComptrollerLensInterface", "numberOfBytes": "20" }, - "t_contract(IPrime)22911": { + "t_contract(IDeviationBoundedOracle)8437": { + "encoding": "inplace", + "label": "contract IDeviationBoundedOracle", + "numberOfBytes": "20" + }, + "t_contract(IPrime)42902": { "encoding": "inplace", "label": "contract IPrime", "numberOfBytes": "20" }, - "t_contract(ResilientOracleInterface)992": { + "t_contract(ResilientOracleInterface)8467": { "encoding": "inplace", "label": "contract ResilientOracleInterface", "numberOfBytes": "20" }, - "t_contract(VAIControllerInterface)25733": { + "t_contract(VAIControllerInterface)51683": { "encoding": "inplace", "label": "contract VAIControllerInterface", "numberOfBytes": "20" }, - "t_contract(VToken)32634": { + "t_contract(VToken)58633": { "encoding": "inplace", "label": "contract VToken", "numberOfBytes": "20" }, - "t_mapping(t_address,t_array(t_contract(VToken)32634)dyn_storage)": { + "t_mapping(t_address,t_array(t_contract(VToken)58633)dyn_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => contract VToken[])", "numberOfBytes": "32", - "value": "t_array(t_contract(VToken)32634)dyn_storage" + "value": "t_array(t_contract(VToken)58633)dyn_storage" }, "t_mapping(t_address,t_bool)": { "encoding": "mapping", @@ -1742,19 +1771,19 @@ "numberOfBytes": "32", "value": "t_mapping(t_uint256,t_bool)" }, - "t_mapping(t_address,t_struct(FacetFunctionSelectors)1967_storage)": { + "t_mapping(t_address,t_struct(FacetFunctionSelectors)10070_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV13Storage.FacetFunctionSelectors)", "numberOfBytes": "32", - "value": "t_struct(FacetFunctionSelectors)1967_storage" + "value": "t_struct(FacetFunctionSelectors)10070_storage" }, - "t_mapping(t_address,t_struct(VenusMarketState)1775_storage)": { + "t_mapping(t_address,t_struct(VenusMarketState)9878_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct ComptrollerV1Storage.VenusMarketState)", "numberOfBytes": "32", - "value": "t_struct(VenusMarketState)1775_storage" + "value": "t_struct(VenusMarketState)9878_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -1770,12 +1799,12 @@ "numberOfBytes": "32", "value": "t_uint96" }, - "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)1961_storage)": { + "t_mapping(t_bytes4,t_struct(FacetAddressAndPosition)10064_storage)": { "encoding": "mapping", "key": "t_bytes4", "label": "mapping(bytes4 => struct ComptrollerV13Storage.FacetAddressAndPosition)", "numberOfBytes": "32", - "value": "t_struct(FacetAddressAndPosition)1961_storage" + "value": "t_struct(FacetAddressAndPosition)10064_storage" }, "t_mapping(t_uint256,t_bool)": { "encoding": "mapping", @@ -1784,31 +1813,31 @@ "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_uint96,t_struct(PoolData)2023_storage)": { + "t_mapping(t_uint96,t_struct(PoolData)10126_storage)": { "encoding": "mapping", "key": "t_uint96", "label": "mapping(uint96 => struct ComptrollerV17Storage.PoolData)", "numberOfBytes": "32", - "value": "t_struct(PoolData)2023_storage" + "value": "t_struct(PoolData)10126_storage" }, - "t_mapping(t_userDefinedValueType(PoolMarketId)11427,t_struct(Market)1736_storage)": { + "t_mapping(t_userDefinedValueType(PoolMarketId)19777,t_struct(Market)9839_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(PoolMarketId)11427", + "key": "t_userDefinedValueType(PoolMarketId)19777", "label": "mapping(PoolMarketId => struct ComptrollerV1Storage.Market)", "numberOfBytes": "32", - "value": "t_struct(Market)1736_storage" + "value": "t_struct(Market)9839_storage" }, "t_string_storage": { "encoding": "bytes", "label": "string", "numberOfBytes": "32" }, - "t_struct(FacetAddressAndPosition)1961_storage": { + "t_struct(FacetAddressAndPosition)10064_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetAddressAndPosition", "members": [ { - "astId": 1958, + "astId": 10061, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "facetAddress", "offset": 0, @@ -1816,7 +1845,7 @@ "type": "t_address" }, { - "astId": 1960, + "astId": 10063, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "functionSelectorPosition", "offset": 20, @@ -1826,12 +1855,12 @@ ], "numberOfBytes": "32" }, - "t_struct(FacetFunctionSelectors)1967_storage": { + "t_struct(FacetFunctionSelectors)10070_storage": { "encoding": "inplace", "label": "struct ComptrollerV13Storage.FacetFunctionSelectors", "members": [ { - "astId": 1964, + "astId": 10067, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "functionSelectors", "offset": 0, @@ -1839,7 +1868,7 @@ "type": "t_array(t_bytes4)dyn_storage" }, { - "astId": 1966, + "astId": 10069, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "facetAddressPosition", "offset": 0, @@ -1849,12 +1878,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Market)1736_storage": { + "t_struct(Market)9839_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.Market", "members": [ { - "astId": 1712, + "astId": 9815, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isListed", "offset": 0, @@ -1862,7 +1891,7 @@ "type": "t_bool" }, { - "astId": 1715, + "astId": 9818, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "collateralFactorMantissa", "offset": 0, @@ -1870,7 +1899,7 @@ "type": "t_uint256" }, { - "astId": 1720, + "astId": 9823, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "accountMembership", "offset": 0, @@ -1878,7 +1907,7 @@ "type": "t_mapping(t_address,t_bool)" }, { - "astId": 1723, + "astId": 9826, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isVenus", "offset": 0, @@ -1886,7 +1915,7 @@ "type": "t_bool" }, { - "astId": 1726, + "astId": 9829, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "liquidationThresholdMantissa", "offset": 0, @@ -1894,7 +1923,7 @@ "type": "t_uint256" }, { - "astId": 1729, + "astId": 9832, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "liquidationIncentiveMantissa", "offset": 0, @@ -1902,7 +1931,7 @@ "type": "t_uint256" }, { - "astId": 1732, + "astId": 9835, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "poolId", "offset": 0, @@ -1910,7 +1939,7 @@ "type": "t_uint96" }, { - "astId": 1735, + "astId": 9838, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isBorrowAllowed", "offset": 12, @@ -1920,12 +1949,12 @@ ], "numberOfBytes": "224" }, - "t_struct(PoolData)2023_storage": { + "t_struct(PoolData)10126_storage": { "encoding": "inplace", "label": "struct ComptrollerV17Storage.PoolData", "members": [ { - "astId": 2012, + "astId": 10115, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "label", "offset": 0, @@ -1933,7 +1962,7 @@ "type": "t_string_storage" }, { - "astId": 2016, + "astId": 10119, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "vTokens", "offset": 0, @@ -1941,7 +1970,7 @@ "type": "t_array(t_address)dyn_storage" }, { - "astId": 2019, + "astId": 10122, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "isActive", "offset": 0, @@ -1949,7 +1978,7 @@ "type": "t_bool" }, { - "astId": 2022, + "astId": 10125, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "allowCorePoolFallback", "offset": 1, @@ -1959,12 +1988,12 @@ ], "numberOfBytes": "96" }, - "t_struct(VenusMarketState)1775_storage": { + "t_struct(VenusMarketState)9878_storage": { "encoding": "inplace", "label": "struct ComptrollerV1Storage.VenusMarketState", "members": [ { - "astId": 1771, + "astId": 9874, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "index", "offset": 0, @@ -1972,7 +2001,7 @@ "type": "t_uint224" }, { - "astId": 1774, + "astId": 9877, "contract": "contracts/Comptroller/Diamond/Diamond.sol:Diamond", "label": "block", "offset": 28, @@ -2002,7 +2031,7 @@ "label": "uint96", "numberOfBytes": "12" }, - "t_userDefinedValueType(PoolMarketId)11427": { + "t_userDefinedValueType(PoolMarketId)19777": { "encoding": "inplace", "label": "PoolMarketId", "numberOfBytes": "32" diff --git a/deployments/bsctestnet/VaiUnitroller_Implementation.json b/deployments/bsctestnet/VaiUnitroller_Implementation.json index 2f1aa44b6..4f26bfb80 100644 --- a/deployments/bsctestnet/VaiUnitroller_Implementation.json +++ b/deployments/bsctestnet/VaiUnitroller_Implementation.json @@ -1,5 +1,5 @@ { - "address": "0xC1CE7174D58f177fd2b418292A6E60CDE9bACF78", + "address": "0xd2848305b0ee7646C930240D79549D50d6Ed024F", "abi": [ { "anonymous": false, @@ -1091,28 +1091,28 @@ "type": "function" } ], - "transactionHash": "0xddccd94e9431fe41442908354f122bc33c5decb321753b07d628529a966f8fcf", + "transactionHash": "0x7a14b0382fbd73a549761f5a216f05f10dda57fcb50c4f78a0813761a03688e5", "receipt": { "to": null, - "from": "0x33C6476F88eeA28D7E7900F759B4597704Ef95B7", - "contractAddress": "0xC1CE7174D58f177fd2b418292A6E60CDE9bACF78", + "from": "0x4cD6300F5cb8D6BbA5E646131c3522664C10dF11", + "contractAddress": "0xd2848305b0ee7646C930240D79549D50d6Ed024F", "transactionIndex": 0, - "gasUsed": "3658121", + "gasUsed": "3762806", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x37b73467e0bbe6bf1b3231ba8205421264d81b9c7b1940bea47fd83a2df1a783", - "transactionHash": "0xddccd94e9431fe41442908354f122bc33c5decb321753b07d628529a966f8fcf", + "blockHash": "0xeedd1bf06601eb583efaaaf3803edd5a17b1cab6aa462770ad7638c27194c2a4", + "transactionHash": "0x7a14b0382fbd73a549761f5a216f05f10dda57fcb50c4f78a0813761a03688e5", "logs": [], - "blockNumber": 72683448, - "cumulativeGasUsed": "3658121", + "blockNumber": 102774945, + "cumulativeGasUsed": "3762806", "status": 1, "byzantium": true }, "args": [], - "numDeployments": 5, - "solcInputHash": "fb463cfbcc602d71a84def594b9868a3", - "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"LiquidateVAI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeAmount\",\"type\":\"uint256\"}],\"name\":\"MintFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"previousMintEnabledOnlyForPrimeHolder\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newMintEnabledOnlyForPrimeHolder\",\"type\":\"bool\"}],\"name\":\"MintOnlyForPrimeHolder\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mintVAIAmount\",\"type\":\"uint256\"}],\"name\":\"MintVAI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"NewAccessControl\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"oldComptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"newComptroller\",\"type\":\"address\"}],\"name\":\"NewComptroller\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPrime\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPrime\",\"type\":\"address\"}],\"name\":\"NewPrime\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"}],\"name\":\"NewTreasuryAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"}],\"name\":\"NewTreasuryGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldTreasuryPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"NewTreasuryPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBaseRateMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBaseRateMantissa\",\"type\":\"uint256\"}],\"name\":\"NewVAIBaseRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFloatRateMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFlatRateMantissa\",\"type\":\"uint256\"}],\"name\":\"NewVAIFloatRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMintCap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMintCap\",\"type\":\"uint256\"}],\"name\":\"NewVAIMintCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldReceiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newReceiver\",\"type\":\"address\"}],\"name\":\"NewVAIReceiver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldVaiToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newVaiToken\",\"type\":\"address\"}],\"name\":\"NewVaiToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayVAIAmount\",\"type\":\"uint256\"}],\"name\":\"RepayVAI\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_ID\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_VAI_MINT_INDEX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VAIUnitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"comptroller_\",\"type\":\"address\"}],\"name\":\"_setComptroller\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"_setTreasuryData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControl\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accrueVAIInterest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRateMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptroller\",\"outputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"floatRateMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"getMintableVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"getVAICalculateRepayAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"getVAIMinterInterestIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVAIRepayAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIRepayRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIRepayRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isVenusVAIInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"contract VTokenInterface\",\"name\":\"vTokenCollateral\",\"type\":\"address\"}],\"name\":\"liquidateVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintCap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintEnabledOnlyForPrimeHolder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"mintVAIAmount\",\"type\":\"uint256\"}],\"name\":\"mintVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"pastVAIInterest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingVAIControllerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"receiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repayVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repayVAIBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"setAccessControl\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBaseRateMantissa\",\"type\":\"uint256\"}],\"name\":\"setBaseRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFloatRateMantissa\",\"type\":\"uint256\"}],\"name\":\"setFloatRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_mintCap\",\"type\":\"uint256\"}],\"name\":\"setMintCap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"prime_\",\"type\":\"address\"}],\"name\":\"setPrimeToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newReceiver\",\"type\":\"address\"}],\"name\":\"setReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vai_\",\"type\":\"address\"}],\"name\":\"setVAIToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"toggleOnlyPrimeHolderMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiControllerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusVAIMinterIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setComptroller(address)\":{\"details\":\"Admin function to set a new comptroller\",\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setTreasuryData(address,address,uint256)\":{\"params\":{\"newTreasuryAddress\":\"New Treasury Address\",\"newTreasuryGuardian\":\"New Treasury Guardian address\",\"newTreasuryPercent\":\"New fee percentage for minting VAI that is sent to the treasury\"}},\"getMintableVAI(address)\":{\"params\":{\"minter\":\"The account to check mintable VAI\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\",\"_1\":\"Mintable amount (with 18 decimals)\"}},\"getVAIAddress()\":{\"returns\":{\"_0\":\"The address of VAI\"}},\"getVAICalculateRepayAmount(address,uint256)\":{\"params\":{\"borrower\":\"The address of the VAI borrower\",\"repayAmount\":\"The amount of VAI being returned\"},\"returns\":{\"_0\":\"Amount of VAI to be burned\",\"_1\":\"Amount of VAI the user needs to pay in current interest\",\"_2\":\"Amount of VAI the user needs to pay in past interest\"}},\"getVAIMinterInterestIndex(address)\":{\"params\":{\"minter\":\"Address of VAI minter\"},\"returns\":{\"_0\":\"uint256 Returns the interest rate index for a minter\"}},\"getVAIRepayAmount(address)\":{\"params\":{\"account\":\"The address of the VAI borrower\"},\"returns\":{\"_0\":\"(uint256) The total amount of VAI the user needs to repay\"}},\"getVAIRepayRate()\":{\"returns\":{\"_0\":\"uint256 Yearly VAI interest rate\"}},\"getVAIRepayRatePerBlock()\":{\"returns\":{\"_0\":\"uint256 Interest rate per bock\"}},\"liquidateVAI(address,uint256,address)\":{\"params\":{\"borrower\":\"The borrower of vai to be liquidated\",\"repayAmount\":\"The amount of the underlying borrowed asset to repay\",\"vTokenCollateral\":\"The market in which to seize collateral from the borrower\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"mintVAI(uint256)\":{\"details\":\"If the Comptroller address is not set, minting is a no-op and the function returns the success code.\",\"params\":{\"mintVAIAmount\":\"The amount of the VAI to be minted.\"},\"returns\":{\"_0\":\"0 on success, otherwise an error code\"}},\"repayVAI(uint256)\":{\"details\":\"If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\",\"params\":{\"amount\":\"The amount of VAI to be repaid.\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"repayVAIBehalf(address,uint256)\":{\"details\":\"If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\",\"params\":{\"amount\":\"The amount of VAI to be repaid.\",\"borrower\":\"The account to repay the debt for.\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"setAccessControl(address)\":{\"details\":\"Admin function to set the access control address\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"}},\"setBaseRate(uint256)\":{\"params\":{\"newBaseRateMantissa\":\"the base rate multiplied by 10**18\"}},\"setFloatRate(uint256)\":{\"params\":{\"newFloatRateMantissa\":\"the VAI float rate multiplied by 10**18\"}},\"setMintCap(uint256)\":{\"params\":{\"_mintCap\":\"the amount of VAI that can be minted\"}},\"setPrimeToken(address)\":{\"params\":{\"prime_\":\"The new address of the prime token contract\"}},\"setReceiver(address)\":{\"params\":{\"newReceiver\":\"the address of the VAI fee receiver\"}},\"setVAIToken(address)\":{\"params\":{\"vai_\":\"The new address of the VAI token contract\"}},\"toggleOnlyPrimeHolderMint()\":{\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}}},\"title\":\"VAI Comptroller\",\"version\":1},\"userdoc\":{\"events\":{\"LiquidateVAI(address,address,uint256,address,uint256)\":{\"notice\":\"Event emitted when a borrow is liquidated\"},\"MintFee(address,uint256)\":{\"notice\":\"Event emitted when VAIs are minted and fee are transferred\"},\"MintOnlyForPrimeHolder(bool,bool)\":{\"notice\":\"Emitted when mint for prime holder is changed\"},\"MintVAI(address,uint256)\":{\"notice\":\"Event emitted when VAI is minted\"},\"NewAccessControl(address,address)\":{\"notice\":\"Emitted when access control address is changed by admin\"},\"NewComptroller(address,address)\":{\"notice\":\"Emitted when Comptroller is changed\"},\"NewPrime(address,address)\":{\"notice\":\"Emitted when Prime is changed\"},\"NewTreasuryAddress(address,address)\":{\"notice\":\"Emitted when treasury address is changed\"},\"NewTreasuryGuardian(address,address)\":{\"notice\":\"Emitted when treasury guardian is changed\"},\"NewTreasuryPercent(uint256,uint256)\":{\"notice\":\"Emitted when treasury percent is changed\"},\"NewVAIBaseRate(uint256,uint256)\":{\"notice\":\"Emiitted when VAI base rate is changed\"},\"NewVAIFloatRate(uint256,uint256)\":{\"notice\":\"Emiitted when VAI float rate is changed\"},\"NewVAIMintCap(uint256,uint256)\":{\"notice\":\"Emiitted when VAI mint cap is changed\"},\"NewVAIReceiver(address,address)\":{\"notice\":\"Emiitted when VAI receiver address is changed\"},\"NewVaiToken(address,address)\":{\"notice\":\"Emitted when VAI token address is changed by admin\"},\"RepayVAI(address,address,uint256)\":{\"notice\":\"Event emitted when VAI is repaid\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_ID()\":{\"notice\":\"poolId for core Pool\"},\"INITIAL_VAI_MINT_INDEX()\":{\"notice\":\"Initial index used in interest computations\"},\"_setComptroller(address)\":{\"notice\":\"Sets a new comptroller\"},\"_setTreasuryData(address,address,uint256)\":{\"notice\":\"Update treasury data\"},\"accessControl()\":{\"notice\":\"Access control manager address\"},\"accrueVAIInterest()\":{\"notice\":\"Accrue interest on outstanding minted VAI\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"baseRateMantissa()\":{\"notice\":\"The base rate for stability fee\"},\"floatRateMantissa()\":{\"notice\":\"The float rate for stability fee\"},\"getMintableVAI(address)\":{\"notice\":\"Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\"},\"getVAIAddress()\":{\"notice\":\"Return the address of the VAI token\"},\"getVAICalculateRepayAmount(address,uint256)\":{\"notice\":\"Calculate how much VAI the user needs to repay\"},\"getVAIMinterInterestIndex(address)\":{\"notice\":\"Get the last updated interest index for a VAI Minter\"},\"getVAIRepayAmount(address)\":{\"notice\":\"Get the current total VAI a user needs to repay\"},\"getVAIRepayRate()\":{\"notice\":\"Gets yearly VAI interest rate based on the VAI price\"},\"getVAIRepayRatePerBlock()\":{\"notice\":\"Get interest rate per block\"},\"isVenusVAIInitialized()\":{\"notice\":\"The Venus VAI state initialized\"},\"liquidateVAI(address,uint256,address)\":{\"notice\":\"The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\"},\"mintCap()\":{\"notice\":\"VAI mint cap\"},\"mintEnabledOnlyForPrimeHolder()\":{\"notice\":\"Tracks if minting is enabled only for prime token holders. Only used if prime is set\"},\"mintVAI(uint256)\":{\"notice\":\"The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance. The amount minted must be less than the user's Account Liquidity and the mint vai limit.\"},\"pastVAIInterest(address)\":{\"notice\":\"Tracks the amount of mintedVAI of a user that represents the accrued interest\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingVAIControllerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"prime()\":{\"notice\":\"The address of the prime contract. It can be a ZERO address\"},\"receiver()\":{\"notice\":\"The address for VAI interest receiver\"},\"repayVAI(uint256)\":{\"notice\":\"The repay function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Before repaying VAI, users must first approve VAIController to access their VAI balance.\"},\"repayVAIBehalf(address,uint256)\":{\"notice\":\"The repay on behalf function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower). Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\"},\"setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"setBaseRate(uint256)\":{\"notice\":\"Set VAI borrow base rate\"},\"setFloatRate(uint256)\":{\"notice\":\"Set VAI borrow float rate\"},\"setMintCap(uint256)\":{\"notice\":\"Set VAI mint cap\"},\"setPrimeToken(address)\":{\"notice\":\"Set the prime token contract address\"},\"setReceiver(address)\":{\"notice\":\"Set VAI stability fee receiver address\"},\"setVAIToken(address)\":{\"notice\":\"Set the VAI token contract address\"},\"toggleOnlyPrimeHolderMint()\":{\"notice\":\"Toggle mint only for prime holder\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"vaiControllerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"vaiMintIndex()\":{\"notice\":\"Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\"},\"venusVAIMinterIndex(address)\":{\"notice\":\"The Venus VAI minter index as of the last time they accrued XVS\"},\"venusVAIState()\":{\"notice\":\"The Venus VAI state\"}},\"notice\":\"This is the implementation contract for the VAIUnitroller proxy\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Tokens/VAI/VAIController.sol\":\"VAIController\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface TwapInterface is OracleInterface {\\n function updateTwap(address asset) external returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x2432799b0d824fc701beb4c30146e912b9aeecf77b5c1635dde6c5fbe6bfc3a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0xb8de7a0684411bc301a5a4a3411656c712a7f94668b3ec617ec27b37cf6cd0ea\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/IVAI.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-or-later\\n// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico\\n\\npragma solidity 0.8.25;\\n\\ninterface IVAI {\\n // --- Auth ---\\n function wards(address) external view returns (uint256);\\n function rely(address guy) external;\\n function deny(address guy) external;\\n\\n // --- BEP20 Data ---\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function version() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint256);\\n\\n function balanceOf(address) external view returns (uint256);\\n function allowance(address, address) external view returns (uint256);\\n function nonces(address) external view returns (uint256);\\n\\n event Approval(address indexed src, address indexed guy, uint256 wad);\\n event Transfer(address indexed src, address indexed dst, uint256 wad);\\n\\n // --- EIP712 niceties ---\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n // bytes32 public constant PERMIT_TYPEHASH = keccak256(\\\"Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)\\\");\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n // --- Token ---\\n function transfer(address dst, uint256 wad) external returns (bool);\\n function transferFrom(address src, address dst, uint256 wad) external returns (bool);\\n function mint(address usr, uint256 wad) external;\\n function burn(address usr, uint256 wad) external;\\n function approve(address usr, uint256 wad) external returns (bool);\\n\\n // --- Alias ---\\n function push(address usr, uint256 wad) external;\\n function pull(address usr, uint256 wad) external;\\n function move(address src, address dst, uint256 wad) external;\\n\\n // --- Approve by signature ---\\n function permit(\\n address holder,\\n address spender,\\n uint256 nonce,\\n uint256 expiry,\\n bool allowed,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0x9d7c391c50cdd8ddadd030694e1fd9ee3456861bc0cca2f2a28a714c6470d0b3\",\"license\":\"AGPL-3.0-or-later\"},\"contracts/Tokens/VAI/VAIController.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { VAIControllerErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { VToken } from \\\"../VTokens/VToken.sol\\\";\\nimport { VAIUnitroller } from \\\"./VAIUnitroller.sol\\\";\\nimport { VAIControllerInterface } from \\\"./VAIControllerInterface.sol\\\";\\nimport { IVAI } from \\\"./IVAI.sol\\\";\\nimport { IPrime } from \\\"../Prime/IPrime.sol\\\";\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\nimport { VAIControllerStorageG4 } from \\\"./VAIControllerStorage.sol\\\";\\n\\n/**\\n * @title VAI Comptroller\\n * @author Venus\\n * @notice This is the implementation contract for the VAIUnitroller proxy\\n */\\ncontract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAIControllerErrorReporter, Exponential {\\n /// @notice Initial index used in interest computations\\n uint256 public constant INITIAL_VAI_MINT_INDEX = 1e18;\\n\\n /// poolId for core Pool\\n uint96 public constant CORE_POOL_ID = 0;\\n\\n /// @notice Emitted when Comptroller is changed\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /// @notice Emitted when mint for prime holder is changed\\n event MintOnlyForPrimeHolder(bool previousMintEnabledOnlyForPrimeHolder, bool newMintEnabledOnlyForPrimeHolder);\\n\\n /// @notice Emitted when Prime is changed\\n event NewPrime(address oldPrime, address newPrime);\\n\\n /// @notice Event emitted when VAI is minted\\n event MintVAI(address minter, uint256 mintVAIAmount);\\n\\n /// @notice Event emitted when VAI is repaid\\n event RepayVAI(address payer, address borrower, uint256 repayVAIAmount);\\n\\n /// @notice Event emitted when a borrow is liquidated\\n event LiquidateVAI(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n address vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /// @notice Emitted when treasury guardian is changed\\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\\n\\n /// @notice Emitted when treasury address is changed\\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\\n\\n /// @notice Emitted when treasury percent is changed\\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\\n\\n /// @notice Event emitted when VAIs are minted and fee are transferred\\n event MintFee(address minter, uint256 feeAmount);\\n\\n /// @notice Emiitted when VAI base rate is changed\\n event NewVAIBaseRate(uint256 oldBaseRateMantissa, uint256 newBaseRateMantissa);\\n\\n /// @notice Emiitted when VAI float rate is changed\\n event NewVAIFloatRate(uint256 oldFloatRateMantissa, uint256 newFlatRateMantissa);\\n\\n /// @notice Emiitted when VAI receiver address is changed\\n event NewVAIReceiver(address oldReceiver, address newReceiver);\\n\\n /// @notice Emiitted when VAI mint cap is changed\\n event NewVAIMintCap(uint256 oldMintCap, uint256 newMintCap);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /// @notice Emitted when VAI token address is changed by admin\\n event NewVaiToken(address oldVaiToken, address newVaiToken);\\n\\n function initialize() external onlyAdmin {\\n require(vaiMintIndex == 0, \\\"already initialized\\\");\\n\\n vaiMintIndex = INITIAL_VAI_MINT_INDEX;\\n accrualBlockNumber = getBlockNumber();\\n mintCap = type(uint256).max;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n function _become(VAIUnitroller unitroller) external {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance.\\n * The amount minted must be less than the user's Account Liquidity and the mint vai limit.\\n * @dev If the Comptroller address is not set, minting is a no-op and the function returns the success code.\\n * @param mintVAIAmount The amount of the VAI to be minted.\\n * @return 0 on success, otherwise an error code\\n */\\n // solhint-disable-next-line code-complexity\\n function mintVAI(uint256 mintVAIAmount) external nonReentrant returns (uint256) {\\n if (address(comptroller) == address(0)) {\\n return uint256(Error.NO_ERROR);\\n }\\n\\n require(comptroller.userPoolId(msg.sender) == CORE_POOL_ID, \\\"VAI mint only allowed in the core Pool\\\");\\n\\n _ensureNonzeroAmount(mintVAIAmount);\\n _ensureNotPaused();\\n accrueVAIInterest();\\n\\n uint256 err;\\n address minter = msg.sender;\\n address _vai = vai;\\n uint256 vaiTotalSupply = IVAI(_vai).totalSupply();\\n\\n uint256 vaiNewTotalSupply = add_(vaiTotalSupply, mintVAIAmount);\\n require(vaiNewTotalSupply <= mintCap, \\\"mint cap reached\\\");\\n\\n uint256 accountMintableVAI;\\n (err, accountMintableVAI) = getMintableVAI(minter);\\n require(err == uint256(Error.NO_ERROR), \\\"could not compute mintable amount\\\");\\n\\n // check that user have sufficient mintableVAI balance\\n require(mintVAIAmount <= accountMintableVAI, \\\"minting more than allowed\\\");\\n\\n // Calculate the minted balance based on interest index\\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\\n\\n if (totalMintedVAI > 0) {\\n uint256 repayAmount = getVAIRepayAmount(minter);\\n uint256 remainedAmount = sub_(repayAmount, totalMintedVAI);\\n pastVAIInterest[minter] = add_(pastVAIInterest[minter], remainedAmount);\\n totalMintedVAI = repayAmount;\\n }\\n\\n uint256 accountMintVAINew = add_(totalMintedVAI, mintVAIAmount);\\n err = comptroller.setMintedVAIOf(minter, accountMintVAINew);\\n require(err == uint256(Error.NO_ERROR), \\\"comptroller rejection\\\");\\n\\n uint256 remainedAmount;\\n if (treasuryPercent != 0) {\\n uint256 feeAmount = div_(mul_(mintVAIAmount, treasuryPercent), 1e18);\\n remainedAmount = sub_(mintVAIAmount, feeAmount);\\n IVAI(_vai).mint(treasuryAddress, feeAmount);\\n\\n emit MintFee(minter, feeAmount);\\n } else {\\n remainedAmount = mintVAIAmount;\\n }\\n\\n IVAI(_vai).mint(minter, remainedAmount);\\n vaiMinterInterestIndex[minter] = vaiMintIndex;\\n\\n emit MintVAI(minter, remainedAmount);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice The repay function transfers VAI interest into the protocol and burns the rest,\\n * reducing the borrower's borrow balance. Before repaying VAI, users must first approve\\n * VAIController to access their VAI balance.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAI(uint256 amount) external nonReentrant returns (uint256, uint256) {\\n return _repayVAI(msg.sender, amount);\\n }\\n\\n /**\\n * @notice The repay on behalf function transfers VAI interest into the protocol and burns the rest,\\n * reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower).\\n * Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param borrower The account to repay the debt for.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAIBehalf(address borrower, uint256 amount) external nonReentrant returns (uint256, uint256) {\\n _ensureNonzeroAddress(borrower);\\n return _repayVAI(borrower, amount);\\n }\\n\\n /**\\n * @dev Checks the parameters and the protocol state, accrues interest, and invokes repayVAIFresh.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param borrower The account to repay the debt for.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function _repayVAI(address borrower, uint256 amount) internal returns (uint256, uint256) {\\n if (address(comptroller) == address(0)) {\\n return (0, 0);\\n }\\n _ensureNonzeroAmount(amount);\\n _ensureNotPaused();\\n\\n accrueVAIInterest();\\n return repayVAIFresh(msg.sender, borrower, amount);\\n }\\n\\n /**\\n * @dev Repay VAI, expecting interest to be accrued\\n * @dev Borrowed VAIs are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the VAI\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of VAI being repaid\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAIFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256, uint256) {\\n (uint256 burn, uint256 partOfCurrentInterest, uint256 partOfPastInterest) = getVAICalculateRepayAmount(\\n borrower,\\n repayAmount\\n );\\n\\n IVAI _vai = IVAI(vai);\\n _vai.burn(payer, burn);\\n bool success = _vai.transferFrom(payer, receiver, partOfCurrentInterest);\\n require(success == true, \\\"failed to transfer VAI fee\\\");\\n\\n uint256 vaiBalanceBorrower = comptroller.mintedVAIs(borrower);\\n\\n uint256 accountVAINew = sub_(sub_(vaiBalanceBorrower, burn), partOfPastInterest);\\n pastVAIInterest[borrower] = sub_(pastVAIInterest[borrower], partOfPastInterest);\\n\\n uint256 error = comptroller.setMintedVAIOf(borrower, accountVAINew);\\n // We have to revert upon error since side-effects already happened at this point\\n require(error == uint256(Error.NO_ERROR), \\\"comptroller rejection\\\");\\n\\n uint256 repaidAmount = add_(burn, partOfCurrentInterest);\\n emit RepayVAI(payer, borrower, repaidAmount);\\n\\n return (uint256(Error.NO_ERROR), repaidAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of vai to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external nonReentrant returns (uint256, uint256) {\\n _ensureNotPaused();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != uint256(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateVAIFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateVAIFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral by repay borrowers VAI.\\n * The collateral seized is transferred to the liquidator.\\n * @dev If the Comptroller address is not set, liquidation is a no-op and the function returns the success code.\\n * @param liquidator The address repaying the VAI and seizing collateral\\n * @param borrower The borrower of this VAI to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the VAI to repay\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function liquidateVAIFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint256, uint256) {\\n if (address(comptroller) != address(0)) {\\n accrueVAIInterest();\\n\\n /* Fail if liquidate not allowed */\\n uint256 allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n //if (vTokenCollateral.accrualBlockNumber() != accrualBlockNumber) {\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayVAI fails */\\n (uint256 repayBorrowError, uint256 actualRepayAmount) = repayVAIFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint256(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateVAICalculateSeizeTokens(\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(\\n amountSeizeError == uint256(Error.NO_ERROR),\\n \\\"VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\"\\n );\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"VAI_LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n uint256 seizeError;\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint256(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateVAI(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint256(Error.NO_ERROR), actualRepayAmount);\\n }\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new comptroller\\n * @dev Admin function to set a new comptroller\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface comptroller_) external returns (uint256) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n comptroller = comptroller_;\\n emit NewComptroller(oldComptroller, comptroller_);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the prime token contract address\\n * @param prime_ The new address of the prime token contract\\n */\\n function setPrimeToken(address prime_) external onlyAdmin {\\n emit NewPrime(prime, prime_);\\n prime = prime_;\\n }\\n\\n /**\\n * @notice Set the VAI token contract address\\n * @param vai_ The new address of the VAI token contract\\n */\\n function setVAIToken(address vai_) external onlyAdmin {\\n emit NewVaiToken(vai, vai_);\\n vai = vai_;\\n }\\n\\n /**\\n * @notice Toggle mint only for prime holder\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function toggleOnlyPrimeHolderMint() external returns (uint256) {\\n _ensureAllowed(\\\"toggleOnlyPrimeHolderMint()\\\");\\n\\n if (!mintEnabledOnlyForPrimeHolder && prime == address(0)) {\\n return uint256(Error.REJECTION);\\n }\\n\\n emit MintOnlyForPrimeHolder(mintEnabledOnlyForPrimeHolder, !mintEnabledOnlyForPrimeHolder);\\n mintEnabledOnlyForPrimeHolder = !mintEnabledOnlyForPrimeHolder;\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account total supply balance.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountAmountLocalVars {\\n uint256 oErr;\\n MathError mErr;\\n uint256 sumSupply;\\n uint256 marketSupply;\\n uint256 sumBorrowPlusEffects;\\n uint256 vTokenBalance;\\n uint256 borrowBalance;\\n uint256 exchangeRateMantissa;\\n uint256 oraclePriceMantissa;\\n Exp exchangeRate;\\n Exp oraclePrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate\\n * If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\\n * @param minter The account to check mintable VAI\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\\n * @return Mintable amount (with 18 decimals)\\n */\\n // solhint-disable-next-line code-complexity\\n function getMintableVAI(address minter) public view returns (uint256, uint256) {\\n if (mintEnabledOnlyForPrimeHolder && !IPrime(prime).isUserPrimeHolder(minter)) {\\n return (uint256(Error.REJECTION), 0);\\n }\\n\\n ResilientOracleInterface oracle = comptroller.oracle();\\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\\n\\n AccountAmountLocalVars memory vars; // Holds all our calculation results\\n\\n uint256 accountMintableVAI;\\n uint256 i;\\n\\n /**\\n * We use this formula to calculate mintable VAI amount.\\n * totalSupplyAmount * VAIMintRate - (totalBorrowAmount + mintedVAIOf)\\n */\\n uint256 marketsCount = enteredMarkets.length;\\n for (i = 0; i < marketsCount; i++) {\\n (vars.oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = enteredMarkets[i]\\n .getAccountSnapshot(minter);\\n if (vars.oErr != 0) {\\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (uint256(Error.SNAPSHOT_ERROR), 0);\\n }\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n // Get the normalized price of the asset\\n vars.oraclePriceMantissa = oracle.getUnderlyingPrice(address(enteredMarkets[i]));\\n if (vars.oraclePriceMantissa == 0) {\\n return (uint256(Error.PRICE_ERROR), 0);\\n }\\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\\n\\n (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.oraclePrice);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n // marketSupply = tokensToDenom * vTokenBalance\\n (vars.mErr, vars.marketSupply) = mulScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (, uint256 collateralFactorMantissa, , , , , ) = comptroller.markets(address(enteredMarkets[i]));\\n (vars.mErr, vars.marketSupply) = mulUInt(vars.marketSupply, collateralFactorMantissa);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, vars.marketSupply) = divUInt(vars.marketSupply, 1e18);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, vars.sumSupply) = addUInt(vars.sumSupply, vars.marketSupply);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n // sumBorrowPlusEffects += oraclePrice * borrowBalance\\n (vars.mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(\\n vars.oraclePrice,\\n vars.borrowBalance,\\n vars.sumBorrowPlusEffects\\n );\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n }\\n\\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\\n uint256 repayAmount = 0;\\n\\n if (totalMintedVAI > 0) {\\n repayAmount = getVAIRepayAmount(minter);\\n }\\n\\n (vars.mErr, vars.sumBorrowPlusEffects) = addUInt(vars.sumBorrowPlusEffects, repayAmount);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, accountMintableVAI) = mulUInt(vars.sumSupply, comptroller.vaiMintRate());\\n require(vars.mErr == MathError.NO_ERROR, \\\"VAI_MINT_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (vars.mErr, accountMintableVAI) = divUInt(accountMintableVAI, 10000);\\n require(vars.mErr == MathError.NO_ERROR, \\\"VAI_MINT_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (vars.mErr, accountMintableVAI) = subUInt(accountMintableVAI, vars.sumBorrowPlusEffects);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.REJECTION), 0);\\n }\\n\\n return (uint256(Error.NO_ERROR), accountMintableVAI);\\n }\\n\\n /**\\n * @notice Update treasury data\\n * @param newTreasuryGuardian New Treasury Guardian address\\n * @param newTreasuryAddress New Treasury Address\\n * @param newTreasuryPercent New fee percentage for minting VAI that is sent to the treasury\\n */\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256) {\\n // Check caller is admin\\n if (!(msg.sender == admin || msg.sender == treasuryGuardian)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_TREASURY_OWNER_CHECK);\\n }\\n\\n require(newTreasuryPercent < 1e18, \\\"treasury percent cap overflow\\\");\\n\\n address oldTreasuryGuardian = treasuryGuardian;\\n address oldTreasuryAddress = treasuryAddress;\\n uint256 oldTreasuryPercent = treasuryPercent;\\n\\n treasuryGuardian = newTreasuryGuardian;\\n treasuryAddress = newTreasuryAddress;\\n treasuryPercent = newTreasuryPercent;\\n\\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Gets yearly VAI interest rate based on the VAI price\\n * @return uint256 Yearly VAI interest rate\\n */\\n function getVAIRepayRate() public view returns (uint256) {\\n ResilientOracleInterface oracle = comptroller.oracle();\\n MathError mErr;\\n\\n if (baseRateMantissa > 0) {\\n if (floatRateMantissa > 0) {\\n uint256 oraclePrice = oracle.getUnderlyingPrice(getVAIAddress());\\n if (1e18 > oraclePrice) {\\n uint256 delta;\\n uint256 rate;\\n\\n (mErr, delta) = subUInt(1e18, oraclePrice);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = mulUInt(delta, floatRateMantissa);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = divUInt(delta, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, rate) = addUInt(delta, baseRateMantissa);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n return rate;\\n } else {\\n return baseRateMantissa;\\n }\\n } else {\\n return baseRateMantissa;\\n }\\n } else {\\n return 0;\\n }\\n }\\n\\n /**\\n * @notice Get interest rate per block\\n * @return uint256 Interest rate per bock\\n */\\n function getVAIRepayRatePerBlock() public view returns (uint256) {\\n uint256 yearlyRate = getVAIRepayRate();\\n\\n MathError mErr;\\n uint256 rate;\\n\\n (mErr, rate) = divUInt(yearlyRate, getBlocksPerYear());\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Get the last updated interest index for a VAI Minter\\n * @param minter Address of VAI minter\\n * @return uint256 Returns the interest rate index for a minter\\n */\\n function getVAIMinterInterestIndex(address minter) public view returns (uint256) {\\n uint256 storedIndex = vaiMinterInterestIndex[minter];\\n // If the user minted VAI before the stability fee was introduced, accrue\\n // starting from stability fee launch\\n if (storedIndex == 0) {\\n return INITIAL_VAI_MINT_INDEX;\\n }\\n return storedIndex;\\n }\\n\\n /**\\n * @notice Get the current total VAI a user needs to repay\\n * @param account The address of the VAI borrower\\n * @return (uint256) The total amount of VAI the user needs to repay\\n */\\n function getVAIRepayAmount(address account) public view returns (uint256) {\\n MathError mErr;\\n uint256 delta;\\n\\n uint256 amount = comptroller.mintedVAIs(account);\\n uint256 interest = pastVAIInterest[account];\\n uint256 totalMintedVAI;\\n uint256 newInterest;\\n\\n (mErr, totalMintedVAI) = subUInt(amount, interest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = subUInt(vaiMintIndex, getVAIMinterInterestIndex(account));\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, newInterest) = mulUInt(delta, totalMintedVAI);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, newInterest) = divUInt(newInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, amount) = addUInt(amount, newInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n return amount;\\n }\\n\\n /**\\n * @notice Calculate how much VAI the user needs to repay\\n * @param borrower The address of the VAI borrower\\n * @param repayAmount The amount of VAI being returned\\n * @return Amount of VAI to be burned\\n * @return Amount of VAI the user needs to pay in current interest\\n * @return Amount of VAI the user needs to pay in past interest\\n */\\n function getVAICalculateRepayAmount(\\n address borrower,\\n uint256 repayAmount\\n ) public view returns (uint256, uint256, uint256) {\\n MathError mErr;\\n uint256 totalRepayAmount = getVAIRepayAmount(borrower);\\n uint256 currentInterest;\\n\\n (mErr, currentInterest) = subUInt(totalRepayAmount, comptroller.mintedVAIs(borrower));\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, currentInterest) = addUInt(pastVAIInterest[borrower], currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n uint256 burn;\\n uint256 partOfCurrentInterest = currentInterest;\\n uint256 partOfPastInterest = pastVAIInterest[borrower];\\n\\n if (repayAmount >= totalRepayAmount) {\\n (mErr, burn) = subUInt(totalRepayAmount, currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n } else {\\n uint256 delta;\\n\\n (mErr, delta) = mulUInt(repayAmount, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PART_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = divUInt(delta, totalRepayAmount);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PART_CALCULATION_FAILED\\\");\\n\\n uint256 totalMintedAmount;\\n (mErr, totalMintedAmount) = subUInt(totalRepayAmount, currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_MINTED_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, burn) = mulUInt(totalMintedAmount, delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, burn) = divUInt(burn, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfCurrentInterest) = mulUInt(currentInterest, delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfCurrentInterest) = divUInt(partOfCurrentInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfPastInterest) = mulUInt(pastVAIInterest[borrower], delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PAST_INTEREST_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfPastInterest) = divUInt(partOfPastInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PAST_INTEREST_CALCULATION_FAILED\\\");\\n }\\n\\n return (burn, partOfCurrentInterest, partOfPastInterest);\\n }\\n\\n /**\\n * @notice Accrue interest on outstanding minted VAI\\n */\\n function accrueVAIInterest() public {\\n MathError mErr;\\n uint256 delta;\\n\\n (mErr, delta) = mulUInt(getVAIRepayRatePerBlock(), getBlockNumber() - accrualBlockNumber);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_INTEREST_ACCRUE_FAILED\\\");\\n\\n (mErr, delta) = addUInt(delta, vaiMintIndex);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_INTEREST_ACCRUE_FAILED\\\");\\n\\n vaiMintIndex = delta;\\n accrualBlockNumber = getBlockNumber();\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlAddress New address for the access control\\n */\\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\\n _ensureNonzeroAddress(newAccessControlAddress);\\n\\n address oldAccessControlAddress = accessControl;\\n accessControl = newAccessControlAddress;\\n emit NewAccessControl(oldAccessControlAddress, accessControl);\\n }\\n\\n /**\\n * @notice Set VAI borrow base rate\\n * @param newBaseRateMantissa the base rate multiplied by 10**18\\n */\\n function setBaseRate(uint256 newBaseRateMantissa) external {\\n _ensureAllowed(\\\"setBaseRate(uint256)\\\");\\n\\n uint256 old = baseRateMantissa;\\n baseRateMantissa = newBaseRateMantissa;\\n emit NewVAIBaseRate(old, baseRateMantissa);\\n }\\n\\n /**\\n * @notice Set VAI borrow float rate\\n * @param newFloatRateMantissa the VAI float rate multiplied by 10**18\\n */\\n function setFloatRate(uint256 newFloatRateMantissa) external {\\n _ensureAllowed(\\\"setFloatRate(uint256)\\\");\\n\\n uint256 old = floatRateMantissa;\\n floatRateMantissa = newFloatRateMantissa;\\n emit NewVAIFloatRate(old, floatRateMantissa);\\n }\\n\\n /**\\n * @notice Set VAI stability fee receiver address\\n * @param newReceiver the address of the VAI fee receiver\\n */\\n function setReceiver(address newReceiver) external onlyAdmin {\\n _ensureNonzeroAddress(newReceiver);\\n\\n address old = receiver;\\n receiver = newReceiver;\\n emit NewVAIReceiver(old, newReceiver);\\n }\\n\\n /**\\n * @notice Set VAI mint cap\\n * @param _mintCap the amount of VAI that can be minted\\n */\\n function setMintCap(uint256 _mintCap) external {\\n _ensureAllowed(\\\"setMintCap(uint256)\\\");\\n\\n uint256 old = mintCap;\\n mintCap = _mintCap;\\n emit NewVAIMintCap(old, _mintCap);\\n }\\n\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n function getBlocksPerYear() public view virtual returns (uint256) {\\n return 70080000; //(24 * 60 * 60 * 365) / 0.45;\\n }\\n\\n /**\\n * @notice Return the address of the VAI token\\n * @return The address of VAI\\n */\\n function getVAIAddress() public view virtual returns (address) {\\n return vai;\\n }\\n\\n modifier onlyAdmin() {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n _;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n function _ensureAllowed(string memory functionSig) private view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /// @dev Reverts if the protocol is paused\\n function _ensureNotPaused() private view {\\n require(!comptroller.protocolPaused(), \\\"protocol is paused\\\");\\n }\\n\\n /// @dev Reverts if the passed address is zero\\n function _ensureNonzeroAddress(address someone) private pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @dev Reverts if the passed amount is zero\\n function _ensureNonzeroAmount(uint256 amount) private pure {\\n require(amount > 0, \\\"amount can't be zero\\\");\\n }\\n}\\n\",\"keccak256\":\"0xd206ef1c5dc5fad0d01005b8b237f0f4cc370475958f72381a42a89346b26872\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\n\\ncontract VAIUnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public vaiControllerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingVAIControllerImplementation;\\n}\\n\\ncontract VAIControllerStorageG1 is VAIUnitrollerAdminStorage {\\n ComptrollerInterface public comptroller;\\n\\n struct VenusVAIState {\\n /// @notice The last updated venusVAIMintIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice The Venus VAI state\\n VenusVAIState public venusVAIState;\\n\\n /// @notice The Venus VAI state initialized\\n bool public isVenusVAIInitialized;\\n\\n /// @notice The Venus VAI minter index as of the last time they accrued XVS\\n mapping(address => uint256) public venusVAIMinterIndex;\\n}\\n\\ncontract VAIControllerStorageG2 is VAIControllerStorageG1 {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n\\n /// @notice Guard variable for re-entrancy checks\\n bool internal _notEntered;\\n\\n /// @notice The base rate for stability fee\\n uint256 public baseRateMantissa;\\n\\n /// @notice The float rate for stability fee\\n uint256 public floatRateMantissa;\\n\\n /// @notice The address for VAI interest receiver\\n address public receiver;\\n\\n /// @notice Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\\n uint256 public vaiMintIndex;\\n\\n /// @notice Block number that interest was last accrued at\\n uint256 internal accrualBlockNumber;\\n\\n /// @notice Global vaiMintIndex as of the most recent balance-changing action for user\\n mapping(address => uint256) internal vaiMinterInterestIndex;\\n\\n /// @notice Tracks the amount of mintedVAI of a user that represents the accrued interest\\n mapping(address => uint256) public pastVAIInterest;\\n\\n /// @notice VAI mint cap\\n uint256 public mintCap;\\n\\n /// @notice Access control manager address\\n address public accessControl;\\n}\\n\\ncontract VAIControllerStorageG3 is VAIControllerStorageG2 {\\n /// @notice The address of the prime contract. It can be a ZERO address\\n address public prime;\\n\\n /// @notice Tracks if minting is enabled only for prime token holders. Only used if prime is set\\n bool public mintEnabledOnlyForPrimeHolder;\\n}\\n\\ncontract VAIControllerStorageG4 is VAIControllerStorageG3 {\\n /// @notice The address of the VAI token\\n address internal vai;\\n}\\n\",\"keccak256\":\"0x75295c0c9d1e5e7b8726b0d43c260975eb4d8d0b76325360c39723b996b95603\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIUnitroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { VAIControllerErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { VAIUnitrollerAdminStorage } from \\\"./VAIControllerStorage.sol\\\";\\n\\n/**\\n * @title VAI Unitroller\\n * @author Venus\\n * @notice This is the proxy contract for the VAIComptroller\\n */\\ncontract VAIUnitroller is VAIUnitrollerAdminStorage, VAIControllerErrorReporter {\\n /**\\n * @notice Emitted when pendingVAIControllerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingVAIControllerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint256) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingVAIControllerImplementation;\\n\\n pendingVAIControllerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint256) {\\n // Check caller is pendingImplementation\\n if (msg.sender != pendingVAIControllerImplementation) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = vaiControllerImplementation;\\n address oldPendingImplementation = pendingVAIControllerImplementation;\\n\\n vaiControllerImplementation = pendingVAIControllerImplementation;\\n\\n pendingVAIControllerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, vaiControllerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint256) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint256) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n fallback() external {\\n // delegate all other functions to current implementation\\n (bool success, ) = vaiControllerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize())\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize())\\n }\\n default {\\n return(free_mem_ptr, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe33306ad442bbfe51c50572f91005d98cb657649316ca29aa650fa679dbca86\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint vTokenBalance = accountTokens[account];\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), vTokenBalance, borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getSupplyRate(getCashPrior(), totalBorrows, totalReserves, reserveFactorMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(getCashPrior(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = getCashPrior();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n if (cashPrior < totalReservesNew) {\\n _reduceReservesFresh(cashPrior);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(oldComptroller, newComptroller);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // mintBelahfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, 1e18);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(address borrower, address payable receiver, uint borrowAmount) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n /* If repayAmount == type(uint256).max, repayAmount = accountBorrows */\\n if (repayAmount == type(uint256).max) {\\n vars.repayAmount = vars.accountBorrows;\\n } else {\\n vars.repayAmount = repayAmount;\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // totalReserves - reduceAmount\\n uint totalReservesNew = totalReserves - reduceAmount;\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReservesNew;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReservesNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // Used to store old model for use in the event that is emitted on success\\n InterestRateModelV8 oldInterestRateModel;\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Track the market's current interest rate model\\n oldInterestRateModel = interestRateModel;\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply\\n */\\n uint totalCash = getCashPrior();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0x24ceb1a473f6e51ec1a7085b0a5b734c0104001bfddd3165b672e3ad2d5467d4\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[50] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0x1409d08c6eb3181b2a62913e1c9457a57ce747c062dbf89d6aa568e316add079\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0xad8d795a0011f59304cae938f062a72a998710c01db94f9a813b4f2f00c9534b\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0xf03faf89ad2689a29f0d456c1add258bc09bcf484840170154a32e129500818e\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", - "bytecode": "0x6080604052348015600e575f80fd5b506141218061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061028b575f3560e01c8063691e45ac11610161578063b49b1005116100ca578063d24febad11610084578063d24febad146105a1578063e44e6168146105b4578063ee1fa41e146105fa578063f20fd8f41461060e578063f7260d3e1461062d578063f851a44014610640575f80fd5b8063b49b100514610547578063b9ee87261461054f578063c32094c714610557578063c5f956af1461056a578063c7ee005e1461057d578063cbeb2b2814610590575f80fd5b806378c2f9221161011b57806378c2f922146104de5780637a37c5d0146104f15780638129fc1c14610510578063b06bb42614610518578063b2b481bc1461052b578063b2eafc3914610534575f80fd5b8063691e45ac1461046f5780636fe74a211461049d578063718da7ee146104b0578063741de148146104c357806375c3de43146104cd57806376c71ca1146104d5575f80fd5b80633785d1d6116102035780635ce73240116101bd5780635ce732401461040c5780635fe3b5671461041557806360c954ef1461042857806361b3311c146104455780636509795414610458578063657bdf9414610467575f80fd5b80633785d1d6146103a45780633b5a0a64146103b75780633b72fbef146103ca5780634070a0c9146103d35780634576b5db146103e65780634712ee7d146103f9575f80fd5b80631d08837b116102545780631d08837b146103265780631d504dc6146103395780631f040ff51461034c578063234f89771461035f57806324650602146103725780632678224714610391575f80fd5b80623b58841461028f57806304ef9d58146102bf57806311b3d5e7146102d657806313007d55146102fe57806319129e5a14610311575b5f80fd5b6002546102a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102c8600a5481565b6040519081526020016102b6565b6102e96102e4366004613ae9565b610652565b604080519283526020830191909152016102b6565b6014546102a2906001600160a01b031681565b61032461031f366004613b28565b61074d565b005b610324610334366004613b43565b6107e1565b610324610347366004613b28565b610854565b6102e961035a366004613b5a565b6109cd565b6102c861036d366004613b28565b610a2a565b6102c8610380366004613b28565b60076020525f908152604090205481565b6001546102a2906001600160a01b031681565b6102e96103b2366004613b28565b610a5f565b6103246103c5366004613b43565b611372565b6102c8600c5481565b6103246103e1366004613b43565b6113e6565b6102c86103f4366004613b28565b611458565b6102c8610407366004613b43565b6114dc565b6102c8600d5481565b6004546102a2906001600160a01b031681565b6006546104359060ff1681565b60405190151581526020016102b6565b610324610453366004613b28565b611ae0565b6102c8670de0b6b3a764000081565b6102c8611b72565b61048261047d366004613b5a565b611c4b565b604080519384526020840192909252908201526060016102b6565b6102e96104ab366004613b43565b6120e8565b6103246104be366004613b28565b61213a565b63042d56006102c8565b6102c86121c6565b6102c860135481565b6102c86104ec366004613b28565b612217565b6104f85f81565b6040516001600160601b0390911681526020016102b6565b6103246123fe565b6003546102a2906001600160a01b031681565b6102c8600f5481565b6008546102a2906001600160a01b031681565b610324612491565b6102c861258b565b610324610565366004613b28565b6127dc565b6009546102a2906001600160a01b031681565b6015546102a2906001600160a01b031681565b6016546001600160a01b03166102a2565b6102c86105af366004613b84565b61286e565b6005546105d6906001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016102b6565b60155461043590600160a01b900460ff1681565b6102c861061c366004613b28565b60126020525f908152604090205481565b600e546102a2906001600160a01b031681565b5f546102a2906001600160a01b031681565b600b545f90819060ff166106815760405162461bcd60e51b815260040161067890613bc2565b60405180910390fd5b600b805460ff19169055610693612a03565b5f836001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303815f875af11580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190613be6565b905080156107245761071981600681111561071257610712613bfd565b6008612ab0565b5f9250925050610736565b61073033878787612b27565b92509250505b600b805460ff191660011790559094909350915050565b5f546001600160a01b031633146107765760405162461bcd60e51b815260040161067890613c11565b61077f81613050565b601480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd491015b60405180910390a15050565b6108166040518060400160405280601481526020017373657442617365526174652875696e743235362960601b81525061309e565b600c80549082905560408051828152602081018490527fc84c32795e68685ec107b0e94ae126ef464095f342c7e2e0fec06a23d2e8677e91016107d5565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b49190613c39565b6001600160a01b0316336001600160a01b0316146109245760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610678565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610961573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109859190613be6565b156109ca5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610678565b50565b600b545f90819060ff166109f35760405162461bcd60e51b815260040161067890613bc2565b600b805460ff19169055610a0684613050565b610a10848461314b565b91509150600b805460ff1916600117905590939092509050565b6001600160a01b0381165f90815260116020526040812054808203610a595750670de0b6b3a764000092915050565b92915050565b6015545f908190600160a01b900460ff168015610ae55750601554604051630e3da90d60e21b81526001600160a01b038581166004830152909116906338f6a43490602401602060405180830381865afa158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae39190613c68565b155b15610af5576002935f9350915050565b5f60045f9054906101000a90046001600160a01b03166001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190613c39565b60048054604051632aff3bff60e21b81526001600160a01b03888116938201939093529293505f9291169063abfceffc906024015f60405180830381865afa158015610bb8573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bdf9190810190613ca0565b9050610be9613a43565b81515f9081905b808210156110b657848281518110610c0a57610c0a613d60565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038b811660048301529091169063c37f68e290602401608060405180830381865afa158015610c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613d74565b60e088015260c087015260a086015280855215610ca75760035b995f9950975050505050505050565b60405180602001604052808560e00151815250846101200181905250856001600160a01b031663fc57d4df868481518110610ce457610ce4613d60565b60200260200101516040518263ffffffff1660e01b8152600401610d1791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610d32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d569190613be6565b61010085018190525f03610d6b576004610c98565b604080516020810190915261010085015181526101408501819052610120850151610d9591613199565b856020018661016001829052826003811115610db357610db3613bfd565b6003811115610dc457610dc4613bfd565b9052505f905084602001516003811115610de057610de0613bfd565b14610dec576005610c98565b610dff8461016001518560a001516132a6565b6060860181905260208601826003811115610e1c57610e1c613bfd565b6003811115610e2d57610e2d613bfd565b9052505f905084602001516003811115610e4957610e49613bfd565b14610e55576005610c98565b60045485515f916001600160a01b031690638e8f294b90889086908110610e7e57610e7e613d60565b60200260200101516040518263ffffffff1660e01b8152600401610eb191906001600160a01b0391909116815260200190565b60e060405180830381865afa158015610ecc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef09190613dbd565b5050505050915050610f068560600151826132f3565b6060870181905260208701826003811115610f2357610f23613bfd565b6003811115610f3457610f34613bfd565b9052505f905085602001516003811115610f5057610f50613bfd565b14610f685760055b9a5f9a5098505050505050505050565b610f7e8560600151670de0b6b3a7640000613330565b6060870181905260208701826003811115610f9b57610f9b613bfd565b6003811115610fac57610fac613bfd565b9052505f905085602001516003811115610fc857610fc8613bfd565b14610fd4576005610f58565b610fe68560400151866060015161334f565b604087018190526020870182600381111561100357611003613bfd565b600381111561101457611014613bfd565b9052505f90508560200151600381111561103057611030613bfd565b1461103c576005610f58565b6110548561014001518660c001518760800151613372565b608087018190526020870182600381111561107157611071613bfd565b600381111561108257611082613bfd565b9052505f90508560200151600381111561109e5761109e613bfd565b146110aa576005610f58565b50600190910190610bf0565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611103573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111279190613be6565b90505f811561113c576111398b612217565b90505b61114a86608001518261334f565b608088018190526020880182600381111561116757611167613bfd565b600381111561117857611178613bfd565b9052505f90508660200151600381111561119457611194613bfd565b146111ad5760055b9b5f9b509950505050505050505050565b61122e866040015160045f9054906101000a90046001600160a01b03166001600160a01b031663bec04f726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611205573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112299190613be6565b6132f3565b8760200181975082600381111561124757611247613bfd565b600381111561125857611258613bfd565b9052505f90508660200151600381111561127457611274613bfd565b146112915760405162461bcd60e51b815260040161067890613e29565b61129d85612710613330565b876020018197508260038111156112b6576112b6613bfd565b60038111156112c7576112c7613bfd565b9052505f9050866020015160038111156112e3576112e3613bfd565b146113005760405162461bcd60e51b815260040161067890613e29565b61130e8587608001516133c9565b8760200181975082600381111561132757611327613bfd565b600381111561133857611338613bfd565b9052505f90508660200151600381111561135457611354613bfd565b1461136057600261119c565b5f9b949a509398505050505050505050565b6113a860405180604001604052806015815260200174736574466c6f6174526174652875696e743235362960581b81525061309e565b600d80549082905560408051828152602081018490527f546fb35dbbd92233aecc22b5a11a6791e5db7ec14f62e49cbac2a10c0437f56191016107d5565b61141a604051806040016040528060138152602001727365744d696e744361702875696e743235362960681b81525061309e565b601380549082905560408051828152602081018490527f43862b3eea2df8fce70329f3f84cbcad220f47a73be46c5e00df25165a6e169591016107d5565b5f80546001600160a01b0316331461147657610a5960016002612ab0565b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d910160405180910390a15f5b9392505050565b600b545f9060ff166115005760405162461bcd60e51b815260040161067890613bc2565b600b805460ff191690556004546001600160a01b031661152157505f611ace565b60048054604051637376909960e01b815233928101929092525f916001600160a01b0390911690637376909990602401602060405180830381865afa15801561156c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115909190613e6b565b6001600160601b0316146115f55760405162461bcd60e51b815260206004820152602660248201527f564149206d696e74206f6e6c7920616c6c6f77656420696e2074686520636f726044820152651948141bdbdb60d21b6064820152608401610678565b6115fe826133e9565b611606612a03565b61160e612491565b601654604080516318160ddd60e01b815290515f9233926001600160a01b0390911691849183916318160ddd916004808201926020929091908290030181865afa15801561165e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116829190613be6565b90505f61168f828861342f565b90506013548111156116d65760405162461bcd60e51b815260206004820152601060248201526f1b5a5b9d0818d85c081c995858da195960821b6044820152606401610678565b5f6116e085610a5f565b9096509050851561173d5760405162461bcd60e51b815260206004820152602160248201527f636f756c64206e6f7420636f6d70757465206d696e7461626c6520616d6f756e6044820152601d60fa1b6064820152608401610678565b8088111561178d5760405162461bcd60e51b815260206004820152601960248201527f6d696e74696e67206d6f7265207468616e20616c6c6f776564000000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b03888116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa1580156117da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117fe9190613be6565b9050801561185e575f61181087612217565b90505f61181d8284613464565b6001600160a01b0389165f90815260126020526040902054909150611842908261342f565b6001600160a01b0389165f908152601260205260409020555090505b5f611869828b61342f565b6004805460405163fd51a3ad60e01b81526001600160a01b038b81169382019390935260248101849052929350169063fd51a3ad906044016020604051808303815f875af11580156118bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118e19190613be6565b975087156119295760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f600a545f14611a09575f6119516119438d600a5461349d565b670de0b6b3a76400006134de565b905061195d8c82613464565b6009546040516340c10f1960e01b81526001600160a01b039182166004820152602481018490529193508916906340c10f19906044015f604051808303815f87803b1580156119aa575f80fd5b505af11580156119bc573d5f803e3d5ffd5b5050604080516001600160a01b038d168152602081018590527fb0715a6d41a37c1b0672c22c09a31a0642c1fb3f9efa2d5fd5c6d2d891ee78c6935001905060405180910390a150611a0c565b50895b6040516340c10f1960e01b81526001600160a01b038981166004830152602482018390528816906340c10f19906044015f604051808303815f87803b158015611a53575f80fd5b505af1158015611a65573d5f803e3d5ffd5b5050600f546001600160a01b038b165f818152601160209081526040918290209390935580519182529181018590527e2e68ab1600fc5e7290e2ceaa79e2f86b4dbaca84a48421e167e0b40409218a935001905060405180910390a15f99505050505050505050505b600b805460ff19166001179055919050565b5f546001600160a01b03163314611b095760405162461bcd60e51b815260040161067890613c11565b601654604080516001600160a01b03928316815291831660208301527fe45150fb0a88e2274ecbca05ddde9925dd64b6e126ae0fa23ee2d42e668a49d3910160405180910390a1601680546001600160a01b0319166001600160a01b0392909216919091179055565b5f611bb16040518060400160405280601b81526020017f746f67676c654f6e6c795072696d65486f6c6465724d696e742829000000000081525061309e565b601554600160a01b900460ff16158015611bd457506015546001600160a01b0316155b15611bdf5750600290565b60155460408051600160a01b90920460ff16158015835260208301527f8efa7b6021d602e0cdef814b7435609ee40deb2a0352ca676d10045750516a5f910160405180910390a16015805460ff60a01b198116600160a01b9182900460ff16159091021790555f905090565b5f805f805f611c5987612217565b600480546040516315e3f14f60e11b81526001600160a01b038b8116938201939093529293505f92611cd69285921690632bc7e29e90602401602060405180830381865afa158015611cad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd19190613be6565b6133c9565b90935090505f836003811115611cee57611cee613bfd565b14611d0b5760405162461bcd60e51b815260040161067890613e84565b6001600160a01b0388165f90815260126020526040902054611d2d908261334f565b90935090505f836003811115611d4557611d45613bfd565b14611d625760405162461bcd60e51b815260040161067890613e84565b6001600160a01b0388165f908152601260205260408120548290848a10611dc757611d8d85856133c9565b90965092505f866003811115611da557611da5613bfd565b14611dc25760405162461bcd60e51b815260040161067890613e84565b6120d7565b5f611dda8b670de0b6b3a76400006132f3565b90975090505f876003811115611df257611df2613bfd565b14611e3f5760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b611e498187613330565b90975090505f876003811115611e6157611e61613bfd565b14611eae5760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b5f611eb987876133c9565b90985090505f886003811115611ed157611ed1613bfd565b14611f2a5760405162461bcd60e51b8152602060048201526024808201527f5641495f4d494e5445445f414d4f554e545f43414c43554c4154494f4e5f46416044820152631253115160e21b6064820152608401610678565b611f3481836132f3565b90985094505f886003811115611f4c57611f4c613bfd565b14611f695760405162461bcd60e51b815260040161067890613e84565b611f7b85670de0b6b3a7640000613330565b90985094505f886003811115611f9357611f93613bfd565b14611fb05760405162461bcd60e51b815260040161067890613e84565b611fba86836132f3565b90985093505f886003811115611fd257611fd2613bfd565b14611fef5760405162461bcd60e51b815260040161067890613ec6565b61200184670de0b6b3a7640000613330565b90985093505f88600381111561201957612019613bfd565b146120365760405162461bcd60e51b815260040161067890613ec6565b6001600160a01b038d165f9081526012602052604090205461205890836132f3565b90985092505f88600381111561207057612070613bfd565b1461208d5760405162461bcd60e51b815260040161067890613f14565b61209f83670de0b6b3a7640000613330565b90985092505f8860038111156120b7576120b7613bfd565b146120d45760405162461bcd60e51b815260040161067890613f14565b50505b919750955093505050509250925092565b600b545f90819060ff1661210e5760405162461bcd60e51b815260040161067890613bc2565b600b805460ff19169055612122338461314b565b91509150600b805460ff191660011790559092909150565b5f546001600160a01b031633146121635760405162461bcd60e51b815260040161067890613c11565b61216c81613050565b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f4df62dd7d9cc4f480a167c19c616ae5d5bb40db6d0c2bc66dba57068225f00d891016107d5565b5f806121d061258b565b90505f806121e28363042d5600613330565b90925090505f8260038111156121fa576121fa613bfd565b146114d55760405162461bcd60e51b815260040161067890613f58565b600480546040516315e3f14f60e11b81526001600160a01b03848116938201939093525f9283928392839290911690632bc7e29e90602401602060405180830381865afa15801561226a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061228e9190613be6565b6001600160a01b0386165f90815260126020526040812054919250806122b484846133c9565b90965091505f8660038111156122cc576122cc613bfd565b146122e95760405162461bcd60e51b815260040161067890613f99565b6122f8600f54611cd18a610a2a565b90965094505f86600381111561231057612310613bfd565b1461232d5760405162461bcd60e51b815260040161067890613f99565b61233785836132f3565b90965090505f86600381111561234f5761234f613bfd565b1461236c5760405162461bcd60e51b815260040161067890613f99565b61237e81670de0b6b3a7640000613330565b90965090505f86600381111561239657612396613bfd565b146123b35760405162461bcd60e51b815260040161067890613f99565b6123bd848261334f565b90965093505f8660038111156123d5576123d5613bfd565b146123f25760405162461bcd60e51b815260040161067890613f99565b50919695505050505050565b5f546001600160a01b031633146124275760405162461bcd60e51b815260040161067890613c11565b600f541561246d5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610678565b670de0b6b3a7640000600f55436010555f19601355600b805460ff19166001179055565b5f806124ab61249e6121c6565b6010546112299043613ff6565b90925090505f8260038111156124c3576124c3613bfd565b146125105760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b61251c81600f5461334f565b90925090505f82600381111561253457612534613bfd565b146125815760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b600f555043601055565b60048054604080516307dc0d1d60e41b815290515f9384936001600160a01b031692637dc0d1d092818301926020928290030181865afa1580156125d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125f59190613c39565b90505f80600c5411156127d457600d54156127ca575f826001600160a01b031663fc57d4df61262c6016546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561266e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126929190613be6565b905080670de0b6b3a764000011156127bf575f806126b8670de0b6b3a7640000846133c9565b90945091505f8460038111156126d0576126d0613bfd565b146126ed5760405162461bcd60e51b815260040161067890613f58565b6126f982600d546132f3565b90945091505f84600381111561271157612711613bfd565b1461272e5760405162461bcd60e51b815260040161067890613f58565b61274082670de0b6b3a7640000613330565b90945091505f84600381111561275857612758613bfd565b146127755760405162461bcd60e51b815260040161067890613f58565b61278182600c5461334f565b90945090505f84600381111561279957612799613bfd565b146127b65760405162461bcd60e51b815260040161067890613f58565b95945050505050565b600c54935050505090565b600c549250505090565b5f9250505090565b5f546001600160a01b031633146128055760405162461bcd60e51b815260040161067890613c11565b601554604080516001600160a01b03928316815291831660208301527ffb26401242c61b503dd09c29da64a5d4f451549f574b882a40bcdc64ee68b83c910160405180910390a1601580546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b031633148061289157506008546001600160a01b031633145b6128a8576128a160016017612ab0565b90506114d5565b670de0b6b3a764000082106128ff5760405162461bcd60e51b815260206004820152601d60248201527f74726561737572792070657263656e7420636170206f766572666c6f770000006044820152606401610678565b6008805460098054600a80546001600160a01b03198086166001600160a01b038c81169182179098559084168a8816179094559087905560408051948616808652602086019490945292949091169290917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e8910160405180910390a1604080516001600160a01b038085168252881660208201527f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac910160405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a1505f9695505050505050565b600480546040805163084bf5ab60e31b815290516001600160a01b039092169263425fad589282820192602092908290030181865afa158015612a48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a6c9190613c68565b15612aae5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610678565b565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836006811115612ae457612ae4613bfd565b836017811115612af657612af6613bfd565b6040805192835260208301919091525f9082015260600160405180910390a18260068111156114d5576114d5613bfd565b6004545f9081906001600160a01b03161561304757612b44612491565b60048054604051632fe3f38f60e11b815230928101929092526001600160a01b03858116602484015288811660448401528781166064840152608483018790525f92911690635fc7e71e9060a4016020604051808303815f875af1158015612bae573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd29190613be6565b90508015612bf257612be76002600a83613510565b5f9250925050613047565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c2f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c539190613be6565b14612c6457612be760026009612ab0565b866001600160a01b0316866001600160a01b031603612c8957612be76002600f612ab0565b845f03612c9c57612be76002600d612ab0565b5f198503612cb057612be76002600c612ab0565b5f80612cbd89898961358f565b90925090508115612cf157612ce4826006811115612cdd57612cdd613bfd565b6010612ab0565b5f94509450505050613047565b6004805460405163a78dc77560e01b81526001600160a01b0389811693820193909352602481018490525f928392169063a78dc775906044016040805180830381865afa158015612d44573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d689190614009565b90925090508115612de15760405162461bcd60e51b815260206004820152603760248201527f5641495f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c60448201527f4154455f414d4f554e545f5345495a455f4641494c45440000000000000000006064820152608401610678565b6040516370a0823160e01b81526001600160a01b038b811660048301528291908a16906370a0823190602401602060405180830381865afa158015612e28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e4c9190613be6565b1015612e9a5760405162461bcd60e51b815260206004820152601c60248201527f5641495f4c49515549444154455f5345495a455f544f4f5f4d554348000000006044820152606401610678565b60405163b2a02ff160e01b81526001600160a01b038c811660048301528b81166024830152604482018390525f91908a169063b2a02ff1906064016020604051808303815f875af1158015612ef1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f159190613be6565b90508015612f5c5760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610678565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f42d401f96718a0c42e5cea8108973f0022677b7e2e5f4ee19851b2de7a0394e79181900360a00190a1600480546040516347ef3b3b60e01b815230928101929092526001600160a01b038b811660248401528e811660448401528d811660648401526084830187905260a4830185905216906347ef3b3b9060c4015f604051808303815f87803b15801561301e575f80fd5b505af1158015613030573d5f803e3d5ffd5b505f925061303c915050565b975092955050505050505b94509492505050565b6001600160a01b0381166109ca5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610678565b6014546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906130d09033908590600401614059565b602060405180830381865afa1580156130eb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061310f9190613c68565b6109ca5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610678565b6004545f9081906001600160a01b031661316957505f905080613192565b613172836133e9565b61317a612a03565b613182612491565b61318d33858561358f565b915091505b9250929050565b5f6131af60405180602001604052805f81525090565b5f806131c1865f0151865f01516132f3565b90925090505f8260038111156131d9576131d9613bfd565b146131f7575060408051602081019091525f81529092509050613192565b5f8061321561320f6002670de0b6b3a764000061407c565b8461334f565b90925090505f82600381111561322d5761322d613bfd565b1461324f578160405180602001604052805f8152509550955050505050613192565b5f8061326383670de0b6b3a7640000613330565b90925090505f82600381111561327b5761327b613bfd565b146132885761328861409b565b60408051602081019091529081525f9a909950975050505050505050565b5f805f806132b486866138d5565b90925090505f8260038111156132cc576132cc613bfd565b146132dc575091505f9050613192565b5f6132e68261394a565b9350935050509250929050565b5f80835f0361330657505f905080613192565b83830283613314868361407c565b146133265760025f9250925050613192565b5f92509050613192565b5f80825f036133445750600190505f613192565b5f61318d848661407c565b5f80838301848110613365575f92509050613192565b60025f9250925050613192565b5f805f8061338087876138d5565b90925090505f82600381111561339857613398613bfd565b146133a8575091505f90506133c1565b6133ba6133b48261394a565b8661334f565b9350935050505b935093915050565b5f808383116133de57505f9050818303613192565b50600390505f613192565b5f81116109ca5760405162461bcd60e51b8152602060048201526014602482015273616d6f756e742063616e2774206265207a65726f60601b6044820152606401610678565b5f6114d58383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250613961565b5f6114d58383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061399a565b5f6114d583836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506139c8565b5f6114d583836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613a18565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084600681111561354457613544613bfd565b84601781111561355657613556613bfd565b604080519283526020830191909152810184905260600160405180910390a183600681111561358757613587613bfd565b949350505050565b5f805f805f61359e8787611c4b565b601654604051632770a7eb60e21b81526001600160a01b038d811660048301526024820186905294975092955090935091909116908190639dc29fac906044015f604051808303815f87803b1580156135f5575f80fd5b505af1158015613607573d5f803e3d5ffd5b5050600e546040516323b872dd60e01b81526001600160a01b038d811660048301529182166024820152604481018790525f935090841691506323b872dd906064016020604051808303815f875af1158015613665573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136899190613c68565b90506001811515146136dd5760405162461bcd60e51b815260206004820152601a60248201527f6661696c656420746f207472616e7366657220564149206665650000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa15801561372a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061374e9190613be6565b90505f61376461375e8389613464565b86613464565b6001600160a01b038c165f908152601260205260409020549091506137899086613464565b6001600160a01b03808d165f818152601260205260408082209490945560048054945163fd51a3ad60e01b81529081019290925260248201859052929091169063fd51a3ad906044016020604051808303815f875af11580156137ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138129190613be6565b9050801561385a5760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f613865898961342f565b90507f1db858e6f7e1a0d5e92c10c6507d42b3dabfe0a4867fe90c5a14d9963662ef7e8e8e836040516138b9939291906001600160a01b039384168152919092166020820152604081019190915260600190565b60405180910390a15f9e909d509b505050505050505050505050565b5f6138eb60405180602001604052805f81525090565b5f806138fa865f0151866132f3565b90925090505f82600381111561391257613912613bfd565b14613930575060408051602081019091525f81529092509050613192565b60408051602081019091529081525f969095509350505050565b80515f90610a5990670de0b6b3a76400009061407c565b5f8061396d84866140af565b905082858210156139915760405162461bcd60e51b815260040161067891906140c2565b50949350505050565b5f81848411156139bd5760405162461bcd60e51b815260040161067891906140c2565b506135878385613ff6565b5f8315806139d4575082155b156139e057505f6114d5565b5f6139eb84866140d4565b9050836139f8868361407c565b1483906139915760405162461bcd60e51b815260040161067891906140c2565b5f8183613a385760405162461bcd60e51b815260040161067891906140c2565b50613587838561407c565b6040805161018081019091525f808252602082019081526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001613a9c60405180602001604052805f81525090565b8152602001613ab660405180602001604052805f81525090565b8152602001613ad060405180602001604052805f81525090565b905290565b6001600160a01b03811681146109ca575f80fd5b5f805f60608486031215613afb575f80fd5b8335613b0681613ad5565b9250602084013591506040840135613b1d81613ad5565b809150509250925092565b5f60208284031215613b38575f80fd5b81356114d581613ad5565b5f60208284031215613b53575f80fd5b5035919050565b5f8060408385031215613b6b575f80fd5b8235613b7681613ad5565b946020939093013593505050565b5f805f60608486031215613b96575f80fd5b8335613ba181613ad5565b92506020840135613bb181613ad5565b929592945050506040919091013590565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b5f60208284031215613bf6575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b6020808252600e908201526d37b7363c9030b236b4b71031b0b760911b604082015260600190565b5f60208284031215613c49575f80fd5b81516114d581613ad5565b80518015158114613c63575f80fd5b919050565b5f60208284031215613c78575f80fd5b6114d582613c54565b634e487b7160e01b5f52604160045260245ffd5b8051613c6381613ad5565b5f6020808385031215613cb1575f80fd5b825167ffffffffffffffff80821115613cc8575f80fd5b818501915085601f830112613cdb575f80fd5b815181811115613ced57613ced613c81565b8060051b604051601f19603f83011681018181108582111715613d1257613d12613c81565b604052918252848201925083810185019188831115613d2f575f80fd5b938501935b82851015613d5457613d4585613c95565b84529385019392850192613d34565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215613d87575f80fd5b505082516020840151604085015160609095015191969095509092509050565b80516001600160601b0381168114613c63575f80fd5b5f805f805f805f60e0888a031215613dd3575f80fd5b613ddc88613c54565b965060208801519550613df160408901613c54565b94506060880151935060808801519250613e0d60a08901613da7565b9150613e1b60c08901613c54565b905092959891949750929550565b60208082526022908201527f5641495f4d494e545f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b5f60208284031215613e7b575f80fd5b6114d582613da7565b60208082526022908201527f5641495f4255524e5f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b6020808252602e908201527f5641495f43555252454e545f494e5445524553545f414d4f554e545f43414c4360408201526d155310551253d397d1905253115160921b606082015260800190565b60208082526024908201527f5641495f504153545f494e5445524553545f43414c43554c4154494f4e5f46416040820152631253115160e21b606082015260800190565b60208082526021908201527f5641495f52455041595f524154455f43414c43554c4154494f4e5f4641494c456040820152601160fa1b606082015260800190565b60208082526029908201527f5641495f544f54414c5f52455041595f414d4f554e545f43414c43554c41544960408201526813d397d1905253115160ba1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a5957610a59613fe2565b5f806040838503121561401a575f80fd5b505080516020909101519092909150565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f906135879083018461402b565b5f8261409657634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52600160045260245ffd5b80820180821115610a5957610a59613fe2565b602081525f6114d5602083018461402b565b8082028115828204841417610a5957610a59613fe256fea26469706673582212200ef15b6b7b15c1ccd6e2253973c2553bb634afc0c39fd76759cbd01b1c70c89264736f6c63430008190033", - "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061028b575f3560e01c8063691e45ac11610161578063b49b1005116100ca578063d24febad11610084578063d24febad146105a1578063e44e6168146105b4578063ee1fa41e146105fa578063f20fd8f41461060e578063f7260d3e1461062d578063f851a44014610640575f80fd5b8063b49b100514610547578063b9ee87261461054f578063c32094c714610557578063c5f956af1461056a578063c7ee005e1461057d578063cbeb2b2814610590575f80fd5b806378c2f9221161011b57806378c2f922146104de5780637a37c5d0146104f15780638129fc1c14610510578063b06bb42614610518578063b2b481bc1461052b578063b2eafc3914610534575f80fd5b8063691e45ac1461046f5780636fe74a211461049d578063718da7ee146104b0578063741de148146104c357806375c3de43146104cd57806376c71ca1146104d5575f80fd5b80633785d1d6116102035780635ce73240116101bd5780635ce732401461040c5780635fe3b5671461041557806360c954ef1461042857806361b3311c146104455780636509795414610458578063657bdf9414610467575f80fd5b80633785d1d6146103a45780633b5a0a64146103b75780633b72fbef146103ca5780634070a0c9146103d35780634576b5db146103e65780634712ee7d146103f9575f80fd5b80631d08837b116102545780631d08837b146103265780631d504dc6146103395780631f040ff51461034c578063234f89771461035f57806324650602146103725780632678224714610391575f80fd5b80623b58841461028f57806304ef9d58146102bf57806311b3d5e7146102d657806313007d55146102fe57806319129e5a14610311575b5f80fd5b6002546102a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102c8600a5481565b6040519081526020016102b6565b6102e96102e4366004613ae9565b610652565b604080519283526020830191909152016102b6565b6014546102a2906001600160a01b031681565b61032461031f366004613b28565b61074d565b005b610324610334366004613b43565b6107e1565b610324610347366004613b28565b610854565b6102e961035a366004613b5a565b6109cd565b6102c861036d366004613b28565b610a2a565b6102c8610380366004613b28565b60076020525f908152604090205481565b6001546102a2906001600160a01b031681565b6102e96103b2366004613b28565b610a5f565b6103246103c5366004613b43565b611372565b6102c8600c5481565b6103246103e1366004613b43565b6113e6565b6102c86103f4366004613b28565b611458565b6102c8610407366004613b43565b6114dc565b6102c8600d5481565b6004546102a2906001600160a01b031681565b6006546104359060ff1681565b60405190151581526020016102b6565b610324610453366004613b28565b611ae0565b6102c8670de0b6b3a764000081565b6102c8611b72565b61048261047d366004613b5a565b611c4b565b604080519384526020840192909252908201526060016102b6565b6102e96104ab366004613b43565b6120e8565b6103246104be366004613b28565b61213a565b63042d56006102c8565b6102c86121c6565b6102c860135481565b6102c86104ec366004613b28565b612217565b6104f85f81565b6040516001600160601b0390911681526020016102b6565b6103246123fe565b6003546102a2906001600160a01b031681565b6102c8600f5481565b6008546102a2906001600160a01b031681565b610324612491565b6102c861258b565b610324610565366004613b28565b6127dc565b6009546102a2906001600160a01b031681565b6015546102a2906001600160a01b031681565b6016546001600160a01b03166102a2565b6102c86105af366004613b84565b61286e565b6005546105d6906001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016102b6565b60155461043590600160a01b900460ff1681565b6102c861061c366004613b28565b60126020525f908152604090205481565b600e546102a2906001600160a01b031681565b5f546102a2906001600160a01b031681565b600b545f90819060ff166106815760405162461bcd60e51b815260040161067890613bc2565b60405180910390fd5b600b805460ff19169055610693612a03565b5f836001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303815f875af11580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190613be6565b905080156107245761071981600681111561071257610712613bfd565b6008612ab0565b5f9250925050610736565b61073033878787612b27565b92509250505b600b805460ff191660011790559094909350915050565b5f546001600160a01b031633146107765760405162461bcd60e51b815260040161067890613c11565b61077f81613050565b601480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd491015b60405180910390a15050565b6108166040518060400160405280601481526020017373657442617365526174652875696e743235362960601b81525061309e565b600c80549082905560408051828152602081018490527fc84c32795e68685ec107b0e94ae126ef464095f342c7e2e0fec06a23d2e8677e91016107d5565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b49190613c39565b6001600160a01b0316336001600160a01b0316146109245760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610678565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610961573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109859190613be6565b156109ca5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610678565b50565b600b545f90819060ff166109f35760405162461bcd60e51b815260040161067890613bc2565b600b805460ff19169055610a0684613050565b610a10848461314b565b91509150600b805460ff1916600117905590939092509050565b6001600160a01b0381165f90815260116020526040812054808203610a595750670de0b6b3a764000092915050565b92915050565b6015545f908190600160a01b900460ff168015610ae55750601554604051630e3da90d60e21b81526001600160a01b038581166004830152909116906338f6a43490602401602060405180830381865afa158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae39190613c68565b155b15610af5576002935f9350915050565b5f60045f9054906101000a90046001600160a01b03166001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa158015610b46573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b6a9190613c39565b60048054604051632aff3bff60e21b81526001600160a01b03888116938201939093529293505f9291169063abfceffc906024015f60405180830381865afa158015610bb8573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610bdf9190810190613ca0565b9050610be9613a43565b81515f9081905b808210156110b657848281518110610c0a57610c0a613d60565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038b811660048301529091169063c37f68e290602401608060405180830381865afa158015610c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613d74565b60e088015260c087015260a086015280855215610ca75760035b995f9950975050505050505050565b60405180602001604052808560e00151815250846101200181905250856001600160a01b031663fc57d4df868481518110610ce457610ce4613d60565b60200260200101516040518263ffffffff1660e01b8152600401610d1791906001600160a01b0391909116815260200190565b602060405180830381865afa158015610d32573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d569190613be6565b61010085018190525f03610d6b576004610c98565b604080516020810190915261010085015181526101408501819052610120850151610d9591613199565b856020018661016001829052826003811115610db357610db3613bfd565b6003811115610dc457610dc4613bfd565b9052505f905084602001516003811115610de057610de0613bfd565b14610dec576005610c98565b610dff8461016001518560a001516132a6565b6060860181905260208601826003811115610e1c57610e1c613bfd565b6003811115610e2d57610e2d613bfd565b9052505f905084602001516003811115610e4957610e49613bfd565b14610e55576005610c98565b60045485515f916001600160a01b031690638e8f294b90889086908110610e7e57610e7e613d60565b60200260200101516040518263ffffffff1660e01b8152600401610eb191906001600160a01b0391909116815260200190565b60e060405180830381865afa158015610ecc573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ef09190613dbd565b5050505050915050610f068560600151826132f3565b6060870181905260208701826003811115610f2357610f23613bfd565b6003811115610f3457610f34613bfd565b9052505f905085602001516003811115610f5057610f50613bfd565b14610f685760055b9a5f9a5098505050505050505050565b610f7e8560600151670de0b6b3a7640000613330565b6060870181905260208701826003811115610f9b57610f9b613bfd565b6003811115610fac57610fac613bfd565b9052505f905085602001516003811115610fc857610fc8613bfd565b14610fd4576005610f58565b610fe68560400151866060015161334f565b604087018190526020870182600381111561100357611003613bfd565b600381111561101457611014613bfd565b9052505f90508560200151600381111561103057611030613bfd565b1461103c576005610f58565b6110548561014001518660c001518760800151613372565b608087018190526020870182600381111561107157611071613bfd565b600381111561108257611082613bfd565b9052505f90508560200151600381111561109e5761109e613bfd565b146110aa576005610f58565b50600190910190610bf0565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611103573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111279190613be6565b90505f811561113c576111398b612217565b90505b61114a86608001518261334f565b608088018190526020880182600381111561116757611167613bfd565b600381111561117857611178613bfd565b9052505f90508660200151600381111561119457611194613bfd565b146111ad5760055b9b5f9b509950505050505050505050565b61122e866040015160045f9054906101000a90046001600160a01b03166001600160a01b031663bec04f726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611205573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112299190613be6565b6132f3565b8760200181975082600381111561124757611247613bfd565b600381111561125857611258613bfd565b9052505f90508660200151600381111561127457611274613bfd565b146112915760405162461bcd60e51b815260040161067890613e29565b61129d85612710613330565b876020018197508260038111156112b6576112b6613bfd565b60038111156112c7576112c7613bfd565b9052505f9050866020015160038111156112e3576112e3613bfd565b146113005760405162461bcd60e51b815260040161067890613e29565b61130e8587608001516133c9565b8760200181975082600381111561132757611327613bfd565b600381111561133857611338613bfd565b9052505f90508660200151600381111561135457611354613bfd565b1461136057600261119c565b5f9b949a509398505050505050505050565b6113a860405180604001604052806015815260200174736574466c6f6174526174652875696e743235362960581b81525061309e565b600d80549082905560408051828152602081018490527f546fb35dbbd92233aecc22b5a11a6791e5db7ec14f62e49cbac2a10c0437f56191016107d5565b61141a604051806040016040528060138152602001727365744d696e744361702875696e743235362960681b81525061309e565b601380549082905560408051828152602081018490527f43862b3eea2df8fce70329f3f84cbcad220f47a73be46c5e00df25165a6e169591016107d5565b5f80546001600160a01b0316331461147657610a5960016002612ab0565b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d910160405180910390a15f5b9392505050565b600b545f9060ff166115005760405162461bcd60e51b815260040161067890613bc2565b600b805460ff191690556004546001600160a01b031661152157505f611ace565b60048054604051637376909960e01b815233928101929092525f916001600160a01b0390911690637376909990602401602060405180830381865afa15801561156c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115909190613e6b565b6001600160601b0316146115f55760405162461bcd60e51b815260206004820152602660248201527f564149206d696e74206f6e6c7920616c6c6f77656420696e2074686520636f726044820152651948141bdbdb60d21b6064820152608401610678565b6115fe826133e9565b611606612a03565b61160e612491565b601654604080516318160ddd60e01b815290515f9233926001600160a01b0390911691849183916318160ddd916004808201926020929091908290030181865afa15801561165e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116829190613be6565b90505f61168f828861342f565b90506013548111156116d65760405162461bcd60e51b815260206004820152601060248201526f1b5a5b9d0818d85c081c995858da195960821b6044820152606401610678565b5f6116e085610a5f565b9096509050851561173d5760405162461bcd60e51b815260206004820152602160248201527f636f756c64206e6f7420636f6d70757465206d696e7461626c6520616d6f756e6044820152601d60fa1b6064820152608401610678565b8088111561178d5760405162461bcd60e51b815260206004820152601960248201527f6d696e74696e67206d6f7265207468616e20616c6c6f776564000000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b03888116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa1580156117da573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906117fe9190613be6565b9050801561185e575f61181087612217565b90505f61181d8284613464565b6001600160a01b0389165f90815260126020526040902054909150611842908261342f565b6001600160a01b0389165f908152601260205260409020555090505b5f611869828b61342f565b6004805460405163fd51a3ad60e01b81526001600160a01b038b81169382019390935260248101849052929350169063fd51a3ad906044016020604051808303815f875af11580156118bd573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118e19190613be6565b975087156119295760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f600a545f14611a09575f6119516119438d600a5461349d565b670de0b6b3a76400006134de565b905061195d8c82613464565b6009546040516340c10f1960e01b81526001600160a01b039182166004820152602481018490529193508916906340c10f19906044015f604051808303815f87803b1580156119aa575f80fd5b505af11580156119bc573d5f803e3d5ffd5b5050604080516001600160a01b038d168152602081018590527fb0715a6d41a37c1b0672c22c09a31a0642c1fb3f9efa2d5fd5c6d2d891ee78c6935001905060405180910390a150611a0c565b50895b6040516340c10f1960e01b81526001600160a01b038981166004830152602482018390528816906340c10f19906044015f604051808303815f87803b158015611a53575f80fd5b505af1158015611a65573d5f803e3d5ffd5b5050600f546001600160a01b038b165f818152601160209081526040918290209390935580519182529181018590527e2e68ab1600fc5e7290e2ceaa79e2f86b4dbaca84a48421e167e0b40409218a935001905060405180910390a15f99505050505050505050505b600b805460ff19166001179055919050565b5f546001600160a01b03163314611b095760405162461bcd60e51b815260040161067890613c11565b601654604080516001600160a01b03928316815291831660208301527fe45150fb0a88e2274ecbca05ddde9925dd64b6e126ae0fa23ee2d42e668a49d3910160405180910390a1601680546001600160a01b0319166001600160a01b0392909216919091179055565b5f611bb16040518060400160405280601b81526020017f746f67676c654f6e6c795072696d65486f6c6465724d696e742829000000000081525061309e565b601554600160a01b900460ff16158015611bd457506015546001600160a01b0316155b15611bdf5750600290565b60155460408051600160a01b90920460ff16158015835260208301527f8efa7b6021d602e0cdef814b7435609ee40deb2a0352ca676d10045750516a5f910160405180910390a16015805460ff60a01b198116600160a01b9182900460ff16159091021790555f905090565b5f805f805f611c5987612217565b600480546040516315e3f14f60e11b81526001600160a01b038b8116938201939093529293505f92611cd69285921690632bc7e29e90602401602060405180830381865afa158015611cad573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611cd19190613be6565b6133c9565b90935090505f836003811115611cee57611cee613bfd565b14611d0b5760405162461bcd60e51b815260040161067890613e84565b6001600160a01b0388165f90815260126020526040902054611d2d908261334f565b90935090505f836003811115611d4557611d45613bfd565b14611d625760405162461bcd60e51b815260040161067890613e84565b6001600160a01b0388165f908152601260205260408120548290848a10611dc757611d8d85856133c9565b90965092505f866003811115611da557611da5613bfd565b14611dc25760405162461bcd60e51b815260040161067890613e84565b6120d7565b5f611dda8b670de0b6b3a76400006132f3565b90975090505f876003811115611df257611df2613bfd565b14611e3f5760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b611e498187613330565b90975090505f876003811115611e6157611e61613bfd565b14611eae5760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b5f611eb987876133c9565b90985090505f886003811115611ed157611ed1613bfd565b14611f2a5760405162461bcd60e51b8152602060048201526024808201527f5641495f4d494e5445445f414d4f554e545f43414c43554c4154494f4e5f46416044820152631253115160e21b6064820152608401610678565b611f3481836132f3565b90985094505f886003811115611f4c57611f4c613bfd565b14611f695760405162461bcd60e51b815260040161067890613e84565b611f7b85670de0b6b3a7640000613330565b90985094505f886003811115611f9357611f93613bfd565b14611fb05760405162461bcd60e51b815260040161067890613e84565b611fba86836132f3565b90985093505f886003811115611fd257611fd2613bfd565b14611fef5760405162461bcd60e51b815260040161067890613ec6565b61200184670de0b6b3a7640000613330565b90985093505f88600381111561201957612019613bfd565b146120365760405162461bcd60e51b815260040161067890613ec6565b6001600160a01b038d165f9081526012602052604090205461205890836132f3565b90985092505f88600381111561207057612070613bfd565b1461208d5760405162461bcd60e51b815260040161067890613f14565b61209f83670de0b6b3a7640000613330565b90985092505f8860038111156120b7576120b7613bfd565b146120d45760405162461bcd60e51b815260040161067890613f14565b50505b919750955093505050509250925092565b600b545f90819060ff1661210e5760405162461bcd60e51b815260040161067890613bc2565b600b805460ff19169055612122338461314b565b91509150600b805460ff191660011790559092909150565b5f546001600160a01b031633146121635760405162461bcd60e51b815260040161067890613c11565b61216c81613050565b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f4df62dd7d9cc4f480a167c19c616ae5d5bb40db6d0c2bc66dba57068225f00d891016107d5565b5f806121d061258b565b90505f806121e28363042d5600613330565b90925090505f8260038111156121fa576121fa613bfd565b146114d55760405162461bcd60e51b815260040161067890613f58565b600480546040516315e3f14f60e11b81526001600160a01b03848116938201939093525f9283928392839290911690632bc7e29e90602401602060405180830381865afa15801561226a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061228e9190613be6565b6001600160a01b0386165f90815260126020526040812054919250806122b484846133c9565b90965091505f8660038111156122cc576122cc613bfd565b146122e95760405162461bcd60e51b815260040161067890613f99565b6122f8600f54611cd18a610a2a565b90965094505f86600381111561231057612310613bfd565b1461232d5760405162461bcd60e51b815260040161067890613f99565b61233785836132f3565b90965090505f86600381111561234f5761234f613bfd565b1461236c5760405162461bcd60e51b815260040161067890613f99565b61237e81670de0b6b3a7640000613330565b90965090505f86600381111561239657612396613bfd565b146123b35760405162461bcd60e51b815260040161067890613f99565b6123bd848261334f565b90965093505f8660038111156123d5576123d5613bfd565b146123f25760405162461bcd60e51b815260040161067890613f99565b50919695505050505050565b5f546001600160a01b031633146124275760405162461bcd60e51b815260040161067890613c11565b600f541561246d5760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610678565b670de0b6b3a7640000600f55436010555f19601355600b805460ff19166001179055565b5f806124ab61249e6121c6565b6010546112299043613ff6565b90925090505f8260038111156124c3576124c3613bfd565b146125105760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b61251c81600f5461334f565b90925090505f82600381111561253457612534613bfd565b146125815760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b600f555043601055565b60048054604080516307dc0d1d60e41b815290515f9384936001600160a01b031692637dc0d1d092818301926020928290030181865afa1580156125d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906125f59190613c39565b90505f80600c5411156127d457600d54156127ca575f826001600160a01b031663fc57d4df61262c6016546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa15801561266e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126929190613be6565b905080670de0b6b3a764000011156127bf575f806126b8670de0b6b3a7640000846133c9565b90945091505f8460038111156126d0576126d0613bfd565b146126ed5760405162461bcd60e51b815260040161067890613f58565b6126f982600d546132f3565b90945091505f84600381111561271157612711613bfd565b1461272e5760405162461bcd60e51b815260040161067890613f58565b61274082670de0b6b3a7640000613330565b90945091505f84600381111561275857612758613bfd565b146127755760405162461bcd60e51b815260040161067890613f58565b61278182600c5461334f565b90945090505f84600381111561279957612799613bfd565b146127b65760405162461bcd60e51b815260040161067890613f58565b95945050505050565b600c54935050505090565b600c549250505090565b5f9250505090565b5f546001600160a01b031633146128055760405162461bcd60e51b815260040161067890613c11565b601554604080516001600160a01b03928316815291831660208301527ffb26401242c61b503dd09c29da64a5d4f451549f574b882a40bcdc64ee68b83c910160405180910390a1601580546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b031633148061289157506008546001600160a01b031633145b6128a8576128a160016017612ab0565b90506114d5565b670de0b6b3a764000082106128ff5760405162461bcd60e51b815260206004820152601d60248201527f74726561737572792070657263656e7420636170206f766572666c6f770000006044820152606401610678565b6008805460098054600a80546001600160a01b03198086166001600160a01b038c81169182179098559084168a8816179094559087905560408051948616808652602086019490945292949091169290917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e8910160405180910390a1604080516001600160a01b038085168252881660208201527f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac910160405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a1505f9695505050505050565b600480546040805163084bf5ab60e31b815290516001600160a01b039092169263425fad589282820192602092908290030181865afa158015612a48573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612a6c9190613c68565b15612aae5760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610678565b565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836006811115612ae457612ae4613bfd565b836017811115612af657612af6613bfd565b6040805192835260208301919091525f9082015260600160405180910390a18260068111156114d5576114d5613bfd565b6004545f9081906001600160a01b03161561304757612b44612491565b60048054604051632fe3f38f60e11b815230928101929092526001600160a01b03858116602484015288811660448401528781166064840152608483018790525f92911690635fc7e71e9060a4016020604051808303815f875af1158015612bae573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612bd29190613be6565b90508015612bf257612be76002600a83613510565b5f9250925050613047565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c2f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c539190613be6565b14612c6457612be760026009612ab0565b866001600160a01b0316866001600160a01b031603612c8957612be76002600f612ab0565b845f03612c9c57612be76002600d612ab0565b5f198503612cb057612be76002600c612ab0565b5f80612cbd89898961358f565b90925090508115612cf157612ce4826006811115612cdd57612cdd613bfd565b6010612ab0565b5f94509450505050613047565b6004805460405163a78dc77560e01b81526001600160a01b0389811693820193909352602481018490525f928392169063a78dc775906044016040805180830381865afa158015612d44573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612d689190614009565b90925090508115612de15760405162461bcd60e51b815260206004820152603760248201527f5641495f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c60448201527f4154455f414d4f554e545f5345495a455f4641494c45440000000000000000006064820152608401610678565b6040516370a0823160e01b81526001600160a01b038b811660048301528291908a16906370a0823190602401602060405180830381865afa158015612e28573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e4c9190613be6565b1015612e9a5760405162461bcd60e51b815260206004820152601c60248201527f5641495f4c49515549444154455f5345495a455f544f4f5f4d554348000000006044820152606401610678565b60405163b2a02ff160e01b81526001600160a01b038c811660048301528b81166024830152604482018390525f91908a169063b2a02ff1906064016020604051808303815f875af1158015612ef1573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f159190613be6565b90508015612f5c5760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610678565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f42d401f96718a0c42e5cea8108973f0022677b7e2e5f4ee19851b2de7a0394e79181900360a00190a1600480546040516347ef3b3b60e01b815230928101929092526001600160a01b038b811660248401528e811660448401528d811660648401526084830187905260a4830185905216906347ef3b3b9060c4015f604051808303815f87803b15801561301e575f80fd5b505af1158015613030573d5f803e3d5ffd5b505f925061303c915050565b975092955050505050505b94509492505050565b6001600160a01b0381166109ca5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610678565b6014546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab906130d09033908590600401614059565b602060405180830381865afa1580156130eb573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061310f9190613c68565b6109ca5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610678565b6004545f9081906001600160a01b031661316957505f905080613192565b613172836133e9565b61317a612a03565b613182612491565b61318d33858561358f565b915091505b9250929050565b5f6131af60405180602001604052805f81525090565b5f806131c1865f0151865f01516132f3565b90925090505f8260038111156131d9576131d9613bfd565b146131f7575060408051602081019091525f81529092509050613192565b5f8061321561320f6002670de0b6b3a764000061407c565b8461334f565b90925090505f82600381111561322d5761322d613bfd565b1461324f578160405180602001604052805f8152509550955050505050613192565b5f8061326383670de0b6b3a7640000613330565b90925090505f82600381111561327b5761327b613bfd565b146132885761328861409b565b60408051602081019091529081525f9a909950975050505050505050565b5f805f806132b486866138d5565b90925090505f8260038111156132cc576132cc613bfd565b146132dc575091505f9050613192565b5f6132e68261394a565b9350935050509250929050565b5f80835f0361330657505f905080613192565b83830283613314868361407c565b146133265760025f9250925050613192565b5f92509050613192565b5f80825f036133445750600190505f613192565b5f61318d848661407c565b5f80838301848110613365575f92509050613192565b60025f9250925050613192565b5f805f8061338087876138d5565b90925090505f82600381111561339857613398613bfd565b146133a8575091505f90506133c1565b6133ba6133b48261394a565b8661334f565b9350935050505b935093915050565b5f808383116133de57505f9050818303613192565b50600390505f613192565b5f81116109ca5760405162461bcd60e51b8152602060048201526014602482015273616d6f756e742063616e2774206265207a65726f60601b6044820152606401610678565b5f6114d58383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250613961565b5f6114d58383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b81525061399a565b5f6114d583836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f770000000000000000008152506139c8565b5f6114d583836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613a18565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084600681111561354457613544613bfd565b84601781111561355657613556613bfd565b604080519283526020830191909152810184905260600160405180910390a183600681111561358757613587613bfd565b949350505050565b5f805f805f61359e8787611c4b565b601654604051632770a7eb60e21b81526001600160a01b038d811660048301526024820186905294975092955090935091909116908190639dc29fac906044015f604051808303815f87803b1580156135f5575f80fd5b505af1158015613607573d5f803e3d5ffd5b5050600e546040516323b872dd60e01b81526001600160a01b038d811660048301529182166024820152604481018790525f935090841691506323b872dd906064016020604051808303815f875af1158015613665573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906136899190613c68565b90506001811515146136dd5760405162461bcd60e51b815260206004820152601a60248201527f6661696c656420746f207472616e7366657220564149206665650000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa15801561372a573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061374e9190613be6565b90505f61376461375e8389613464565b86613464565b6001600160a01b038c165f908152601260205260409020549091506137899086613464565b6001600160a01b03808d165f818152601260205260408082209490945560048054945163fd51a3ad60e01b81529081019290925260248201859052929091169063fd51a3ad906044016020604051808303815f875af11580156137ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906138129190613be6565b9050801561385a5760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f613865898961342f565b90507f1db858e6f7e1a0d5e92c10c6507d42b3dabfe0a4867fe90c5a14d9963662ef7e8e8e836040516138b9939291906001600160a01b039384168152919092166020820152604081019190915260600190565b60405180910390a15f9e909d509b505050505050505050505050565b5f6138eb60405180602001604052805f81525090565b5f806138fa865f0151866132f3565b90925090505f82600381111561391257613912613bfd565b14613930575060408051602081019091525f81529092509050613192565b60408051602081019091529081525f969095509350505050565b80515f90610a5990670de0b6b3a76400009061407c565b5f8061396d84866140af565b905082858210156139915760405162461bcd60e51b815260040161067891906140c2565b50949350505050565b5f81848411156139bd5760405162461bcd60e51b815260040161067891906140c2565b506135878385613ff6565b5f8315806139d4575082155b156139e057505f6114d5565b5f6139eb84866140d4565b9050836139f8868361407c565b1483906139915760405162461bcd60e51b815260040161067891906140c2565b5f8183613a385760405162461bcd60e51b815260040161067891906140c2565b50613587838561407c565b6040805161018081019091525f808252602082019081526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001613a9c60405180602001604052805f81525090565b8152602001613ab660405180602001604052805f81525090565b8152602001613ad060405180602001604052805f81525090565b905290565b6001600160a01b03811681146109ca575f80fd5b5f805f60608486031215613afb575f80fd5b8335613b0681613ad5565b9250602084013591506040840135613b1d81613ad5565b809150509250925092565b5f60208284031215613b38575f80fd5b81356114d581613ad5565b5f60208284031215613b53575f80fd5b5035919050565b5f8060408385031215613b6b575f80fd5b8235613b7681613ad5565b946020939093013593505050565b5f805f60608486031215613b96575f80fd5b8335613ba181613ad5565b92506020840135613bb181613ad5565b929592945050506040919091013590565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b5f60208284031215613bf6575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b6020808252600e908201526d37b7363c9030b236b4b71031b0b760911b604082015260600190565b5f60208284031215613c49575f80fd5b81516114d581613ad5565b80518015158114613c63575f80fd5b919050565b5f60208284031215613c78575f80fd5b6114d582613c54565b634e487b7160e01b5f52604160045260245ffd5b8051613c6381613ad5565b5f6020808385031215613cb1575f80fd5b825167ffffffffffffffff80821115613cc8575f80fd5b818501915085601f830112613cdb575f80fd5b815181811115613ced57613ced613c81565b8060051b604051601f19603f83011681018181108582111715613d1257613d12613c81565b604052918252848201925083810185019188831115613d2f575f80fd5b938501935b82851015613d5457613d4585613c95565b84529385019392850192613d34565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215613d87575f80fd5b505082516020840151604085015160609095015191969095509092509050565b80516001600160601b0381168114613c63575f80fd5b5f805f805f805f60e0888a031215613dd3575f80fd5b613ddc88613c54565b965060208801519550613df160408901613c54565b94506060880151935060808801519250613e0d60a08901613da7565b9150613e1b60c08901613c54565b905092959891949750929550565b60208082526022908201527f5641495f4d494e545f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b5f60208284031215613e7b575f80fd5b6114d582613da7565b60208082526022908201527f5641495f4255524e5f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b6020808252602e908201527f5641495f43555252454e545f494e5445524553545f414d4f554e545f43414c4360408201526d155310551253d397d1905253115160921b606082015260800190565b60208082526024908201527f5641495f504153545f494e5445524553545f43414c43554c4154494f4e5f46416040820152631253115160e21b606082015260800190565b60208082526021908201527f5641495f52455041595f524154455f43414c43554c4154494f4e5f4641494c456040820152601160fa1b606082015260800190565b60208082526029908201527f5641495f544f54414c5f52455041595f414d4f554e545f43414c43554c41544960408201526813d397d1905253115160ba1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a5957610a59613fe2565b5f806040838503121561401a575f80fd5b505080516020909101519092909150565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f906135879083018461402b565b5f8261409657634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52600160045260245ffd5b80820180821115610a5957610a59613fe2565b602081525f6114d5602083018461402b565b8082028115828204841417610a5957610a59613fe256fea26469706673582212200ef15b6b7b15c1ccd6e2253973c2553bb634afc0c39fd76759cbd01b1c70c89264736f6c63430008190033", + "numDeployments": 6, + "solcInputHash": "39163d4d4ac1a249a8d521dabc3055c5", + "metadata": "{\"compiler\":{\"version\":\"0.8.25+commit.b61c2a91\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"error\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"info\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"detail\",\"type\":\"uint256\"}],\"name\":\"Failure\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"liquidator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"vTokenCollateral\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"seizeTokens\",\"type\":\"uint256\"}],\"name\":\"LiquidateVAI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feeAmount\",\"type\":\"uint256\"}],\"name\":\"MintFee\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"previousMintEnabledOnlyForPrimeHolder\",\"type\":\"bool\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"newMintEnabledOnlyForPrimeHolder\",\"type\":\"bool\"}],\"name\":\"MintOnlyForPrimeHolder\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"mintVAIAmount\",\"type\":\"uint256\"}],\"name\":\"MintVAI\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldAccessControlAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"NewAccessControl\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"oldComptroller\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"contract ComptrollerInterface\",\"name\":\"newComptroller\",\"type\":\"address\"}],\"name\":\"NewComptroller\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldPrime\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newPrime\",\"type\":\"address\"}],\"name\":\"NewPrime\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryAddress\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"}],\"name\":\"NewTreasuryAddress\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldTreasuryGuardian\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"}],\"name\":\"NewTreasuryGuardian\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldTreasuryPercent\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"NewTreasuryPercent\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldBaseRateMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newBaseRateMantissa\",\"type\":\"uint256\"}],\"name\":\"NewVAIBaseRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldFloatRateMantissa\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newFlatRateMantissa\",\"type\":\"uint256\"}],\"name\":\"NewVAIFloatRate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"oldMintCap\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"newMintCap\",\"type\":\"uint256\"}],\"name\":\"NewVAIMintCap\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldReceiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newReceiver\",\"type\":\"address\"}],\"name\":\"NewVAIReceiver\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"oldVaiToken\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"newVaiToken\",\"type\":\"address\"}],\"name\":\"NewVaiToken\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"payer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"repayVAIAmount\",\"type\":\"uint256\"}],\"name\":\"RepayVAI\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"CORE_POOL_ID\",\"outputs\":[{\"internalType\":\"uint96\",\"name\":\"\",\"type\":\"uint96\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"INITIAL_VAI_MINT_INDEX\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract VAIUnitroller\",\"name\":\"unitroller\",\"type\":\"address\"}],\"name\":\"_become\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"comptroller_\",\"type\":\"address\"}],\"name\":\"_setComptroller\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newTreasuryGuardian\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"newTreasuryAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"newTreasuryPercent\",\"type\":\"uint256\"}],\"name\":\"_setTreasuryData\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accessControl\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"accrueVAIInterest\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"admin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"baseRateMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"comptroller\",\"outputs\":[{\"internalType\":\"contract ComptrollerInterface\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"floatRateMantissa\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getBlocksPerYear\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"getMintableVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"}],\"name\":\"getVAICalculateRepayAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"getVAIMinterInterestIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"getVAIRepayAmount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIRepayRate\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVAIRepayRatePerBlock\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"initialize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"isVenusVAIInitialized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"repayAmount\",\"type\":\"uint256\"},{\"internalType\":\"contract VTokenInterface\",\"name\":\"vTokenCollateral\",\"type\":\"address\"}],\"name\":\"liquidateVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintCap\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mintEnabledOnlyForPrimeHolder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"mintVAIAmount\",\"type\":\"uint256\"}],\"name\":\"mintVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"pastVAIInterest\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingVAIControllerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"prime\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"receiver\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repayVAI\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"borrower\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"repayVAIBehalf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAccessControlAddress\",\"type\":\"address\"}],\"name\":\"setAccessControl\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newBaseRateMantissa\",\"type\":\"uint256\"}],\"name\":\"setBaseRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"newFloatRateMantissa\",\"type\":\"uint256\"}],\"name\":\"setFloatRate\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_mintCap\",\"type\":\"uint256\"}],\"name\":\"setMintCap\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"prime_\",\"type\":\"address\"}],\"name\":\"setPrimeToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newReceiver\",\"type\":\"address\"}],\"name\":\"setReceiver\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"vai_\",\"type\":\"address\"}],\"name\":\"setVAIToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"toggleOnlyPrimeHolderMint\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryGuardian\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"treasuryPercent\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiControllerImplementation\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"vaiMintIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"venusVAIMinterIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"venusVAIState\",\"outputs\":[{\"internalType\":\"uint224\",\"name\":\"index\",\"type\":\"uint224\"},{\"internalType\":\"uint32\",\"name\":\"block\",\"type\":\"uint32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Venus\",\"events\":{\"Failure(uint256,uint256,uint256)\":{\"details\":\"`error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary contract-specific code that enables us to report opaque error codes from upgradeable contracts.*\"}},\"kind\":\"dev\",\"methods\":{\"_setComptroller(address)\":{\"details\":\"Admin function to set a new comptroller\",\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}},\"_setTreasuryData(address,address,uint256)\":{\"params\":{\"newTreasuryAddress\":\"New Treasury Address\",\"newTreasuryGuardian\":\"New Treasury Guardian address\",\"newTreasuryPercent\":\"New fee percentage for minting VAI that is sent to the treasury\"}},\"getMintableVAI(address)\":{\"params\":{\"minter\":\"The account to check mintable VAI\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\",\"_1\":\"Mintable amount (with 18 decimals)\"}},\"getVAIAddress()\":{\"returns\":{\"_0\":\"The address of VAI\"}},\"getVAICalculateRepayAmount(address,uint256)\":{\"params\":{\"borrower\":\"The address of the VAI borrower\",\"repayAmount\":\"The amount of VAI being returned\"},\"returns\":{\"_0\":\"Amount of VAI to be burned\",\"_1\":\"Amount of VAI the user needs to pay in current interest\",\"_2\":\"Amount of VAI the user needs to pay in past interest\"}},\"getVAIMinterInterestIndex(address)\":{\"params\":{\"minter\":\"Address of VAI minter\"},\"returns\":{\"_0\":\"uint256 Returns the interest rate index for a minter\"}},\"getVAIRepayAmount(address)\":{\"params\":{\"account\":\"The address of the VAI borrower\"},\"returns\":{\"_0\":\"(uint256) The total amount of VAI the user needs to repay\"}},\"getVAIRepayRate()\":{\"returns\":{\"_0\":\"uint256 Yearly VAI interest rate\"}},\"getVAIRepayRatePerBlock()\":{\"returns\":{\"_0\":\"uint256 Interest rate per bock\"}},\"liquidateVAI(address,uint256,address)\":{\"params\":{\"borrower\":\"The borrower of vai to be liquidated\",\"repayAmount\":\"The amount of the underlying borrowed asset to repay\",\"vTokenCollateral\":\"The market in which to seize collateral from the borrower\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"mintVAI(uint256)\":{\"details\":\"If the Comptroller address is not set, minting is a no-op and the function returns the success code.\",\"params\":{\"mintVAIAmount\":\"The amount of the VAI to be minted.\"},\"returns\":{\"_0\":\"0 on success, otherwise an error code\"}},\"repayVAI(uint256)\":{\"details\":\"If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\",\"params\":{\"amount\":\"The amount of VAI to be repaid.\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"repayVAIBehalf(address,uint256)\":{\"details\":\"If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\",\"params\":{\"amount\":\"The amount of VAI to be repaid.\",\"borrower\":\"The account to repay the debt for.\"},\"returns\":{\"_0\":\"Error code (0=success, otherwise a failure, see ErrorReporter.sol)\",\"_1\":\"Actual repayment amount\"}},\"setAccessControl(address)\":{\"details\":\"Admin function to set the access control address\",\"params\":{\"newAccessControlAddress\":\"New address for the access control\"}},\"setBaseRate(uint256)\":{\"params\":{\"newBaseRateMantissa\":\"the base rate multiplied by 10**18\"}},\"setFloatRate(uint256)\":{\"params\":{\"newFloatRateMantissa\":\"the VAI float rate multiplied by 10**18\"}},\"setMintCap(uint256)\":{\"params\":{\"_mintCap\":\"the amount of VAI that can be minted\"}},\"setPrimeToken(address)\":{\"params\":{\"prime_\":\"The new address of the prime token contract\"}},\"setReceiver(address)\":{\"params\":{\"newReceiver\":\"the address of the VAI fee receiver\"}},\"setVAIToken(address)\":{\"params\":{\"vai_\":\"The new address of the VAI token contract\"}},\"toggleOnlyPrimeHolderMint()\":{\"returns\":{\"_0\":\"uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\"}}},\"title\":\"VAI Comptroller\",\"version\":1},\"userdoc\":{\"events\":{\"LiquidateVAI(address,address,uint256,address,uint256)\":{\"notice\":\"Event emitted when a borrow is liquidated\"},\"MintFee(address,uint256)\":{\"notice\":\"Event emitted when VAIs are minted and fee are transferred\"},\"MintOnlyForPrimeHolder(bool,bool)\":{\"notice\":\"Emitted when mint for prime holder is changed\"},\"MintVAI(address,uint256)\":{\"notice\":\"Event emitted when VAI is minted\"},\"NewAccessControl(address,address)\":{\"notice\":\"Emitted when access control address is changed by admin\"},\"NewComptroller(address,address)\":{\"notice\":\"Emitted when Comptroller is changed\"},\"NewPrime(address,address)\":{\"notice\":\"Emitted when Prime is changed\"},\"NewTreasuryAddress(address,address)\":{\"notice\":\"Emitted when treasury address is changed\"},\"NewTreasuryGuardian(address,address)\":{\"notice\":\"Emitted when treasury guardian is changed\"},\"NewTreasuryPercent(uint256,uint256)\":{\"notice\":\"Emitted when treasury percent is changed\"},\"NewVAIBaseRate(uint256,uint256)\":{\"notice\":\"Emiitted when VAI base rate is changed\"},\"NewVAIFloatRate(uint256,uint256)\":{\"notice\":\"Emiitted when VAI float rate is changed\"},\"NewVAIMintCap(uint256,uint256)\":{\"notice\":\"Emiitted when VAI mint cap is changed\"},\"NewVAIReceiver(address,address)\":{\"notice\":\"Emiitted when VAI receiver address is changed\"},\"NewVaiToken(address,address)\":{\"notice\":\"Emitted when VAI token address is changed by admin\"},\"RepayVAI(address,address,uint256)\":{\"notice\":\"Event emitted when VAI is repaid\"}},\"kind\":\"user\",\"methods\":{\"CORE_POOL_ID()\":{\"notice\":\"poolId for core Pool\"},\"INITIAL_VAI_MINT_INDEX()\":{\"notice\":\"Initial index used in interest computations\"},\"_setComptroller(address)\":{\"notice\":\"Sets a new comptroller\"},\"_setTreasuryData(address,address,uint256)\":{\"notice\":\"Update treasury data\"},\"accessControl()\":{\"notice\":\"Access control manager address\"},\"accrueVAIInterest()\":{\"notice\":\"Accrue interest on outstanding minted VAI\"},\"admin()\":{\"notice\":\"Administrator for this contract\"},\"baseRateMantissa()\":{\"notice\":\"The base rate for stability fee\"},\"floatRateMantissa()\":{\"notice\":\"The float rate for stability fee\"},\"getMintableVAI(address)\":{\"notice\":\"Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\"},\"getVAIAddress()\":{\"notice\":\"Return the address of the VAI token\"},\"getVAICalculateRepayAmount(address,uint256)\":{\"notice\":\"Calculate how much VAI the user needs to repay\"},\"getVAIMinterInterestIndex(address)\":{\"notice\":\"Get the last updated interest index for a VAI Minter\"},\"getVAIRepayAmount(address)\":{\"notice\":\"Get the current total VAI a user needs to repay\"},\"getVAIRepayRate()\":{\"notice\":\"Gets yearly VAI interest rate based on the VAI price\"},\"getVAIRepayRatePerBlock()\":{\"notice\":\"Get interest rate per block\"},\"isVenusVAIInitialized()\":{\"notice\":\"The Venus VAI state initialized\"},\"liquidateVAI(address,uint256,address)\":{\"notice\":\"The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\"},\"mintCap()\":{\"notice\":\"VAI mint cap\"},\"mintEnabledOnlyForPrimeHolder()\":{\"notice\":\"Tracks if minting is enabled only for prime token holders. Only used if prime is set\"},\"mintVAI(uint256)\":{\"notice\":\"The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance. The amount minted must be less than the user's Account Liquidity and the mint vai limit.\"},\"pastVAIInterest(address)\":{\"notice\":\"Tracks the amount of mintedVAI of a user that represents the accrued interest\"},\"pendingAdmin()\":{\"notice\":\"Pending administrator for this contract\"},\"pendingVAIControllerImplementation()\":{\"notice\":\"Pending brains of Unitroller\"},\"prime()\":{\"notice\":\"The address of the prime contract. It can be a ZERO address\"},\"receiver()\":{\"notice\":\"The address for VAI interest receiver\"},\"repayVAI(uint256)\":{\"notice\":\"The repay function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Before repaying VAI, users must first approve VAIController to access their VAI balance.\"},\"repayVAIBehalf(address,uint256)\":{\"notice\":\"The repay on behalf function transfers VAI interest into the protocol and burns the rest, reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower). Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\"},\"setAccessControl(address)\":{\"notice\":\"Sets the address of the access control of this contract\"},\"setBaseRate(uint256)\":{\"notice\":\"Set VAI borrow base rate\"},\"setFloatRate(uint256)\":{\"notice\":\"Set VAI borrow float rate\"},\"setMintCap(uint256)\":{\"notice\":\"Set VAI mint cap\"},\"setPrimeToken(address)\":{\"notice\":\"Set the prime token contract address\"},\"setReceiver(address)\":{\"notice\":\"Set VAI stability fee receiver address\"},\"setVAIToken(address)\":{\"notice\":\"Set the VAI token contract address\"},\"toggleOnlyPrimeHolderMint()\":{\"notice\":\"Toggle mint only for prime holder\"},\"treasuryAddress()\":{\"notice\":\"Treasury address\"},\"treasuryGuardian()\":{\"notice\":\"Treasury Guardian address\"},\"treasuryPercent()\":{\"notice\":\"Fee percent of accrued interest with decimal 18\"},\"vaiControllerImplementation()\":{\"notice\":\"Active brains of Unitroller\"},\"vaiMintIndex()\":{\"notice\":\"Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\"},\"venusVAIMinterIndex(address)\":{\"notice\":\"The Venus VAI minter index as of the last time they accrued XVS\"},\"venusVAIState()\":{\"notice\":\"The Venus VAI state\"}},\"notice\":\"This is the implementation contract for the VAIUnitroller proxy\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Tokens/VAI/VAIController.sol\":\"VAIController\"},\"evmVersion\":\"cancun\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/access/IAccessControl.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev External interface of AccessControl declared to support ERC165 detection.\\n */\\ninterface IAccessControl {\\n /**\\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\\n *\\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\\n * {RoleAdminChanged} not being emitted signaling this.\\n *\\n * _Available since v3.1._\\n */\\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\\n\\n /**\\n * @dev Emitted when `account` is granted `role`.\\n *\\n * `sender` is the account that originated the contract call, an admin role\\n * bearer except when using {AccessControl-_setupRole}.\\n */\\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Emitted when `account` is revoked `role`.\\n *\\n * `sender` is the account that originated the contract call:\\n * - if using `revokeRole`, it is the admin role bearer\\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\\n */\\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\\n\\n /**\\n * @dev Returns `true` if `account` has been granted `role`.\\n */\\n function hasRole(bytes32 role, address account) external view returns (bool);\\n\\n /**\\n * @dev Returns the admin role that controls `role`. See {grantRole} and\\n * {revokeRole}.\\n *\\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\\n */\\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\\n\\n /**\\n * @dev Grants `role` to `account`.\\n *\\n * If `account` had not been already granted `role`, emits a {RoleGranted}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function grantRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from `account`.\\n *\\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\\n *\\n * Requirements:\\n *\\n * - the caller must have ``role``'s admin role.\\n */\\n function revokeRole(bytes32 role, address account) external;\\n\\n /**\\n * @dev Revokes `role` from the calling account.\\n *\\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\\n * purpose is to provide a mechanism for accounts to lose their privileges\\n * if they are compromised (such as when a trusted device is misplaced).\\n *\\n * If the calling account had been granted `role`, emits a {RoleRevoked}\\n * event.\\n *\\n * Requirements:\\n *\\n * - the caller must be `account`.\\n */\\n function renounceRole(bytes32 role, address account) external;\\n}\\n\",\"keccak256\":\"0x59ce320a585d7e1f163cd70390a0ef2ff9cec832e2aa544293a00692465a7a57\",\"license\":\"MIT\"},\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\nimport \\\"@openzeppelin/contracts/access/IAccessControl.sol\\\";\\n\\n/**\\n * @title IAccessControlManagerV8\\n * @author Venus\\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\\n */\\ninterface IAccessControlManagerV8 is IAccessControl {\\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\\n\\n function revokeCallPermission(\\n address contractAddress,\\n string calldata functionSig,\\n address accountToRevoke\\n ) external;\\n\\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\\n\\n function hasPermission(\\n address account,\\n address contractAddress,\\n string calldata functionSig\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xaa29b098440d0b3a131c5ecdf25ce548790c1b5ac7bf9b5c0264b6af6f7a1e0b\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\ninterface IDeviationBoundedOracle {\\n // --- Enums ---\\n\\n /// @notice Identifies whether a price bound is a minimum or maximum\\n enum PriceBoundType {\\n MIN,\\n MAX\\n }\\n\\n // --- Structs ---\\n\\n /// @notice Per-asset protection state tracking the min/max price window\\n struct MarketProtectionState {\\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\\n uint128 minPrice;\\n /// @notice Highest price observed in the current window\\n uint128 maxPrice;\\n /// @notice Whether protected price is currently being used\\n bool currentlyUsingProtectedPrice;\\n /// @notice Whether this market is whitelisted for bounded pricing\\n bool isBoundedPricingEnabled;\\n /// @notice Timestamp of the last protection trigger \\u2014 reset on every trigger\\n uint64 lastProtectionTriggeredAt;\\n /// @notice Minimum time protection stays active after last trigger\\n uint64 cooldownPeriod;\\n /// @notice The underlying asset address, used to verify initialization\\n address asset;\\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\\n uint128 triggerThreshold;\\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\\n uint128 resetThreshold;\\n }\\n\\n // --- Events ---\\n\\n /// @notice Emitted when protection is initialized for an asset\\n event ProtectionInitialized(\\n address indexed asset,\\n uint128 minPrice,\\n uint128 maxPrice,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold\\n );\\n\\n /// @notice Emitted when protection mode is triggered for an asset\\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\\n\\n /// @notice Emitted when protection mode is disabled for an asset\\n event ProtectionModeExited(address indexed asset);\\n\\n /// @notice Emitted when the keeper updates the minimum price for an asset\\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\\n\\n /// @notice Emitted when the keeper updates the maximum price for an asset\\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\\n\\n /// @notice Emitted when the entry threshold is updated for an asset\\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\\n\\n /// @notice Emitted when the exit threshold is updated for an asset\\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\\n\\n /// @notice Emitted when the cooldown period is updated for an asset\\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\\n\\n /// @notice Emitted when an asset's whitelist status changes\\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\\n\\n // --- Errors ---\\n\\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\\n error MarketNotInitialized(address asset);\\n\\n /// @notice Thrown when trying to initialize an already initialized market\\n error MarketAlreadyInitialized(address asset);\\n\\n /// @notice Thrown when trying to disable protection that is not active\\n error ProtectedPriceInactive(address asset);\\n\\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\\n\\n /// @notice Thrown when trying to disable protection before price range has converged\\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\\n\\n /// @notice Thrown when keeper tries to set minPrice above current spot\\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\\n\\n /// @notice Thrown when keeper tries to set maxPrice below current spot\\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\\n\\n /// @notice Thrown when threshold is set below the minimum allowed value\\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\\n\\n /// @notice Thrown when threshold is set above the maximum allowed value\\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\\n\\n /// @notice Thrown when a price exceeds uint128 max\\n error PriceExceedsUint128(uint256 price);\\n\\n /// @notice Thrown when a zero price is provided where a non-zero price is required\\n error ZeroPriceNotAllowed();\\n\\n /// @notice Thrown when trying to initialize protection for VAI\\n error VAINotAllowed();\\n\\n /// @notice Thrown when trying to update for an asset with active protection\\n error ProtectedPriceActive(address asset);\\n\\n /// @notice Thrown when the lengths of the arrays are not equal\\n error InvalidArrayLength();\\n\\n /// @notice Thrown when the exit threshold is set above the deviation threshold\\n error InvalidResetThreshold(uint256 resetThreshold);\\n\\n // --- Non-view price functions (update window + trigger protection) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- State update (call before view price reads to populate transient cache) ---\\n\\n /**\\n * @notice Updates the protection state for a given vToken, caching the resolved price\\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\\n * reads in the same transaction are served from transient storage.\\n * @param vToken vToken address\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event MinPriceUpdated if a new window minimum is recorded\\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\\n */\\n function updateProtectionState(address vToken) external;\\n\\n // --- View price functions (read stored/cached state only) ---\\n\\n /**\\n * @notice Gets the bounded collateral price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded collateral price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets the bounded debt price for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return price The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\\n\\n /**\\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\\n * @param vToken vToken address\\n * @return collateralPrice The bounded collateral price\\n * @return debtPrice The bounded debt price\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\\n */\\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\\n\\n // --- Keeper functions ---\\n\\n /**\\n * @notice Updates the minimum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMin is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\\n * @custom:event MinPriceUpdated\\n */\\n function updateMinPrice(address asset, uint128 newMin) external;\\n\\n /**\\n * @notice Updates the maximum price in the rolling window for a given asset\\n * @param asset The underlying asset address\\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\\n * @custom:access Only authorized keeper addresses\\n * @custom:error ZeroPriceNotAllowed if newMax is zero\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\\n * @custom:event MaxPriceUpdated\\n */\\n function updateMaxPrice(address asset, uint128 newMax) external;\\n\\n /**\\n * @notice Exits protection mode for a given asset once conditions are met\\n * @param asset The underlying asset address\\n * @custom:access Only authorized monitor/keeper addresses\\n * @custom:error ProtectedPriceInactive if protection is not currently active\\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\\n * @custom:event ProtectionModeExited\\n */\\n function exitProtectionMode(address asset) external;\\n\\n // --- Admin functions (governance-gated) ---\\n\\n /**\\n * @notice Initializes protection parameters for a new asset\\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\\n * confirming the oracle is live for this asset before it is listed.\\n * @param asset The underlying asset address\\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\\n * @custom:access Only Governance\\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\\n * @custom:error VAINotAllowed if asset is the VAI token\\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\\n * @custom:event ProtectionInitialized\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setTokenConfig(\\n address asset,\\n uint64 cooldownPeriod,\\n uint256 triggerThreshold,\\n uint256 resetThreshold,\\n bool enableBoundedPricing\\n ) external;\\n\\n /**\\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\\n * @param assets Array of underlying asset addresses\\n * @param cooldownPeriods Array of cooldown periods (seconds)\\n * @param triggerThresholds Array of trigger thresholds (mantissa)\\n * @param resetThresholds Array of reset thresholds (mantissa)\\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\\n * @custom:access Only Governance\\n * @custom:error InvalidArrayLength if array lengths do not match\\n * @custom:event ProtectionInitialized for each asset\\n * @custom:event BoundedPricingWhitelistUpdated for each asset\\n */\\n function setTokenConfigs(\\n address[] calldata assets,\\n uint64[] calldata cooldownPeriods,\\n uint256[] calldata triggerThresholds,\\n uint256[] calldata resetThresholds,\\n bool[] calldata enableBoundedPricings\\n ) external;\\n\\n /**\\n * @notice Sets the cooldown period for an asset\\n * @param asset The underlying asset address\\n * @param newCooldown The new cooldown period in seconds; must be non-zero\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:event CooldownPeriodSet\\n */\\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\\n\\n /**\\n * @notice Sets the trigger and reset thresholds for an asset\\n * @param asset The underlying asset address\\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\\n * @custom:event TriggerThresholdSet if the trigger threshold changed\\n * @custom:event ResetThresholdSet if the reset threshold changed\\n */\\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\\n\\n /**\\n * @notice Sets whether bounded pricing is enabled for an asset\\n * @param asset The underlying asset address\\n * @param enabled Whether bounded pricing should be enabled for the asset\\n * @custom:access Only Governance\\n * @custom:error MarketNotInitialized if the asset has not been initialized\\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\\n * @custom:event BoundedPricingWhitelistUpdated\\n */\\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\\n\\n // --- View helpers ---\\n\\n /**\\n * @notice Returns the full protection state for an asset\\n * @param asset The underlying asset address\\n * @return minPrice Lowest price observed in the current window\\n * @return maxPrice Highest price observed in the current window\\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\\n * @return cooldownPeriod Minimum time protection stays active after last trigger\\n * @return assetAddr The underlying asset address stored in the struct\\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\\n */\\n function assetProtectionConfig(\\n address asset\\n )\\n external\\n view\\n returns (\\n uint128 minPrice,\\n uint128 maxPrice,\\n bool currentlyUsingProtectedPrice,\\n bool isBoundedPricingEnabled,\\n uint64 lastProtectionTriggeredAt,\\n uint64 cooldownPeriod,\\n address assetAddr,\\n uint128 triggerThreshold,\\n uint128 resetThreshold\\n );\\n\\n /**\\n * @notice Checks if an asset is whitelisted for bounded pricing\\n * @param asset The underlying asset address\\n * @return True if the asset is whitelisted\\n */\\n function isBoundedPricingEnabled(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if the asset is currently using the protected (bounded) price\\n * @param asset The underlying asset address\\n * @return True if the asset is currently using the protected price instead of spot\\n */\\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\\n\\n /**\\n * @notice Checks if protection can be exited for a given asset\\n * @param asset The underlying asset address\\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\\n */\\n function canExitProtection(address asset) external view returns (bool);\\n\\n /**\\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\\n * @param index Array index\\n * @return The asset address at the given index\\n */\\n function allAssets(uint256 index) external view returns (address);\\n\\n /**\\n * @notice Returns all currently whitelisted asset addresses\\n * @return result Array of whitelisted asset addresses\\n */\\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\\n\\n /**\\n * @notice Returns all asset addresses that have ever been initialized\\n * @return Array of all initialized asset addresses\\n */\\n function getInitializedAssets() external view returns (address[] memory);\\n\\n /**\\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\\n * @param assets Array of asset addresses to check\\n * @param proposedMins Keeper's proposed window minimum prices\\n * @param proposedMaxs Keeper's proposed window maximum prices\\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\\n * @custom:error InvalidArrayLength if the input array lengths do not match\\n */\\n function checkAndGetWindowDrift(\\n address[] calldata assets,\\n uint128[] calldata proposedMins,\\n uint128[] calldata proposedMaxs\\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\\n}\\n\",\"keccak256\":\"0x085d9a9abab4d4b594e958b7b74c5ccacd312a860627fd6e339aacf745549d18\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\ninterface OracleInterface {\\n function getPrice(address asset) external view returns (uint256);\\n}\\n\\ninterface ResilientOracleInterface is OracleInterface {\\n function updatePrice(address vToken) external;\\n\\n function updateAssetPrice(address asset) external;\\n\\n function getUnderlyingPrice(address vToken) external view returns (uint256);\\n}\\n\\ninterface BoundValidatorInterface {\\n function validatePriceWithAnchorPrice(\\n address asset,\\n uint256 reporterPrice,\\n uint256 anchorPrice\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xd3bbb7c9eef19e8f467342df6034ef95399a00964646fb8c82b438968ae3a8c0\",\"license\":\"BSD-3-Clause\"},\"@venusprotocol/solidity-utilities/contracts/constants.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity ^0.8.25;\\n\\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\\nuint256 constant EXP_SCALE = 1e18;\\n\\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\\nuint256 constant MANTISSA_ONE = EXP_SCALE;\\n\\n/// @dev The approximate number of seconds per year\\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\\n\",\"keccak256\":\"0x14de93ead464da249af31bea0e3bcfb62ec693bea3475fb4d90f055ac81dc5eb\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/ComptrollerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\nimport { VToken } from \\\"../Tokens/VTokens/VToken.sol\\\";\\nimport { VAIControllerInterface } from \\\"../Tokens/VAI/VAIControllerInterface.sol\\\";\\nimport { WeightFunction } from \\\"./Diamond/interfaces/IFacetBase.sol\\\";\\n\\nenum Action {\\n MINT,\\n REDEEM,\\n BORROW,\\n REPAY,\\n SEIZE,\\n LIQUIDATE,\\n TRANSFER,\\n ENTER_MARKET,\\n EXIT_MARKET\\n}\\n\\ninterface ComptrollerInterface {\\n /// @notice Indicator that this is a Comptroller contract (for inspection)\\n function isComptroller() external pure returns (bool);\\n\\n /*** Assets You Are In ***/\\n\\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\\n\\n function exitMarket(address vToken) external returns (uint);\\n\\n /*** Policy Hooks ***/\\n\\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\\n\\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\\n\\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\\n\\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\\n\\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\\n\\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\\n\\n function executeFlashLoan(\\n address payable onBehalf,\\n address payable receiver,\\n VToken[] calldata vTokens,\\n uint256[] calldata underlyingAmounts,\\n bytes calldata param\\n ) external;\\n\\n function repayBorrowAllowed(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function repayBorrowVerify(\\n address vToken,\\n address payer,\\n address borrower,\\n uint repayAmount,\\n uint borrowerIndex\\n ) external;\\n\\n function liquidateBorrowAllowed(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount\\n ) external returns (uint);\\n\\n function liquidateBorrowVerify(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n uint seizeTokens\\n ) external;\\n\\n function seizeAllowed(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external returns (uint);\\n\\n function seizeVerify(\\n address vTokenCollateral,\\n address vTokenBorrowed,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external;\\n\\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\\n\\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\\n\\n /*** Liquidity/Liquidation Calculations ***/\\n\\n function liquidateCalculateSeizeTokens(\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function liquidateCalculateSeizeTokens(\\n address borrower,\\n address vTokenBorrowed,\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\\n\\n function liquidateVAICalculateSeizeTokens(\\n address vTokenCollateral,\\n uint repayAmount\\n ) external view returns (uint, uint);\\n\\n function getXVSAddress() external view returns (address);\\n\\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\\n\\n function oracle() external view returns (ResilientOracleInterface);\\n\\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\\n\\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\\n\\n function getAssetsIn(address) external view returns (VToken[] memory);\\n\\n function claimVenus(address) external;\\n\\n function venusAccrued(address) external view returns (uint);\\n\\n function venusSupplySpeeds(address) external view returns (uint);\\n\\n function venusBorrowSpeeds(address) external view returns (uint);\\n\\n function getAllMarkets() external view returns (VToken[] memory);\\n\\n function venusSupplierIndex(address, address) external view returns (uint);\\n\\n function venusInitialIndex() external view returns (uint224);\\n\\n function venusBorrowerIndex(address, address) external view returns (uint);\\n\\n function venusBorrowState(address) external view returns (uint224, uint32);\\n\\n function venusSupplyState(address) external view returns (uint224, uint32);\\n\\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\\n\\n function vaiController() external view returns (VAIControllerInterface);\\n\\n function protocolPaused() external view returns (bool);\\n\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n function mintedVAIs(address user) external view returns (uint);\\n\\n function vaiMintRate() external view returns (uint);\\n\\n function authorizedFlashLoan(address account) external view returns (bool);\\n\\n function userPoolId(address account) external view returns (uint96);\\n\\n function getLiquidationIncentive(address vToken) external view returns (uint256);\\n\\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\\n\\n function getEffectiveLtvFactor(\\n address account,\\n address vToken,\\n WeightFunction weightingStrategy\\n ) external view returns (uint256);\\n\\n function lastPoolId() external view returns (uint96);\\n\\n function corePoolId() external pure returns (uint96);\\n\\n function pools(\\n uint96 poolId\\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\\n\\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\\n\\n function poolMarkets(\\n uint96 poolId,\\n address vToken\\n )\\n external\\n view\\n returns (\\n bool isListed,\\n uint256 collateralFactorMantissa,\\n bool isVenus,\\n uint256 liquidationThresholdMantissa,\\n uint256 liquidationIncentiveMantissa,\\n uint96 marketPoolId,\\n bool isBorrowAllowed\\n );\\n\\n function isFlashLoanPaused() external view returns (bool);\\n}\\n\\ninterface IVAIVault {\\n function updatePendingRewards() external;\\n}\\n\\ninterface IComptroller {\\n /*** Treasury Data ***/\\n function treasuryAddress() external view returns (address);\\n\\n function treasuryPercent() external view returns (uint);\\n}\\n\",\"keccak256\":\"0x79fb234214cebf97f6e85c2bbe013977a4cd38ff6146a7c405a2fa9521e0cd4a\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Diamond/interfaces/IFacetBase.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { Action } from \\\"../../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { PoolMarketId } from \\\"../../../Comptroller/Types/PoolMarketId.sol\\\";\\n\\nenum WeightFunction {\\n /// @notice Use the collateral factor of the asset for weighting\\n USE_COLLATERAL_FACTOR,\\n /// @notice Use the liquidation threshold of the asset for weighting\\n USE_LIQUIDATION_THRESHOLD\\n}\\n\\ninterface IFacetBase {\\n /**\\n * @notice The initial XVS rewards index for a market\\n */\\n function venusInitialIndex() external pure returns (uint224);\\n\\n /**\\n * @notice Checks if a certain action is paused on a market\\n * @param action Action id\\n * @param market vToken address\\n */\\n function actionPaused(address market, Action action) external view returns (bool);\\n\\n /**\\n * @notice Returns the XVS address\\n * @return The address of XVS token\\n */\\n function getXVSAddress() external view returns (address);\\n\\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\\n\\n function corePoolId() external pure returns (uint96);\\n}\\n\",\"keccak256\":\"0x454a2e213a5f54fbe7991193b78ae23406234f465c9806f75ee7bf2fe6d1531c\",\"license\":\"BSD-3-Clause\"},\"contracts/Comptroller/Types/PoolMarketId.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\n/// @notice Strongly-typed identifier for pool markets mapping keys\\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\\ntype PoolMarketId is bytes32;\\n\\n \",\"keccak256\":\"0xf68bde30ddd6f8bf08194b493991c2a2ebd3814972f93a804beb9b366004cbe3\",\"license\":\"BSD-3-Clause\"},\"contracts/InterestRateModels/InterestRateModelV8.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Venus's InterestRateModelV8 Interface\\n * @author Venus\\n */\\nabstract contract InterestRateModelV8 {\\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\\n bool public constant isInterestRateModel = true;\\n\\n /**\\n * @notice Calculates the current borrow interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\\n\\n /**\\n * @notice Calculates the current supply interest rate per block\\n * @param cash The total amount of cash the market has\\n * @param borrows The total amount of borrows the market has outstanding\\n * @param reserves The total amnount of reserves the market has\\n * @param reserveFactorMantissa The current reserve factor the market has\\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\\n */\\n function getSupplyRate(\\n uint256 cash,\\n uint256 borrows,\\n uint256 reserves,\\n uint256 reserveFactorMantissa\\n ) external view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x4d5595e761d50a1431c34b39e72dde6c09b0ebccdbe8c5c4e12c8a2ac7b796e1\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/Prime/IPrime.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title IPrime\\n * @author Venus\\n * @notice Interface for Prime Token\\n */\\ninterface IPrime {\\n /**\\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\\n * @param user the account address whose balance was updated\\n */\\n function xvsUpdated(address user) external;\\n\\n /**\\n * @notice accrues interest and updates score for an user for a specific market\\n * @param user the account address for which to accrue interest and update score\\n * @param market the market for which to accrue interest and update score\\n */\\n function accrueInterestAndUpdateScore(address user, address market) external;\\n\\n /**\\n * @notice Distributes income from market since last distribution\\n * @param vToken the market for which to distribute the income\\n */\\n function accrueInterest(address vToken) external;\\n\\n /**\\n * @notice Returns if user is a prime holder\\n * @param isPrimeHolder returns if the user is a prime holder\\n */\\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\\n}\\n\",\"keccak256\":\"0x566ad76b73bfe08c37ec0b06a6e3006171a47e00711270aae92356dbefc6ee73\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/IVAI.sol\":{\"content\":\"// SPDX-License-Identifier: AGPL-3.0-or-later\\n// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico\\n\\npragma solidity 0.8.25;\\n\\ninterface IVAI {\\n // --- Auth ---\\n function wards(address) external view returns (uint256);\\n function rely(address guy) external;\\n function deny(address guy) external;\\n\\n // --- BEP20 Data ---\\n function name() external pure returns (string memory);\\n function symbol() external pure returns (string memory);\\n function version() external pure returns (string memory);\\n function decimals() external pure returns (uint8);\\n function totalSupply() external view returns (uint256);\\n\\n function balanceOf(address) external view returns (uint256);\\n function allowance(address, address) external view returns (uint256);\\n function nonces(address) external view returns (uint256);\\n\\n event Approval(address indexed src, address indexed guy, uint256 wad);\\n event Transfer(address indexed src, address indexed dst, uint256 wad);\\n\\n // --- EIP712 niceties ---\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n // bytes32 public constant PERMIT_TYPEHASH = keccak256(\\\"Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)\\\");\\n function PERMIT_TYPEHASH() external pure returns (bytes32);\\n\\n // --- Token ---\\n function transfer(address dst, uint256 wad) external returns (bool);\\n function transferFrom(address src, address dst, uint256 wad) external returns (bool);\\n function mint(address usr, uint256 wad) external;\\n function burn(address usr, uint256 wad) external;\\n function approve(address usr, uint256 wad) external returns (bool);\\n\\n // --- Alias ---\\n function push(address usr, uint256 wad) external;\\n function pull(address usr, uint256 wad) external;\\n function move(address src, address dst, uint256 wad) external;\\n\\n // --- Approve by signature ---\\n function permit(\\n address holder,\\n address spender,\\n uint256 nonce,\\n uint256 expiry,\\n bool allowed,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n}\\n\",\"keccak256\":\"0x9d7c391c50cdd8ddadd030694e1fd9ee3456861bc0cca2f2a28a714c6470d0b3\",\"license\":\"AGPL-3.0-or-later\"},\"contracts/Tokens/VAI/VAIController.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { ResilientOracleInterface } from \\\"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\\\";\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { VAIControllerErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { VToken } from \\\"../VTokens/VToken.sol\\\";\\nimport { VAIUnitroller } from \\\"./VAIUnitroller.sol\\\";\\nimport { VAIControllerInterface } from \\\"./VAIControllerInterface.sol\\\";\\nimport { IVAI } from \\\"./IVAI.sol\\\";\\nimport { IPrime } from \\\"../Prime/IPrime.sol\\\";\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\nimport { VAIControllerStorageG4 } from \\\"./VAIControllerStorage.sol\\\";\\nimport { IDeviationBoundedOracle } from \\\"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\\\";\\n\\n/**\\n * @title VAI Comptroller\\n * @author Venus\\n * @notice This is the implementation contract for the VAIUnitroller proxy\\n */\\ncontract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAIControllerErrorReporter, Exponential {\\n /// @notice Initial index used in interest computations\\n uint256 public constant INITIAL_VAI_MINT_INDEX = 1e18;\\n\\n /// poolId for core Pool\\n uint96 public constant CORE_POOL_ID = 0;\\n\\n /// @notice Emitted when Comptroller is changed\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /// @notice Emitted when mint for prime holder is changed\\n event MintOnlyForPrimeHolder(bool previousMintEnabledOnlyForPrimeHolder, bool newMintEnabledOnlyForPrimeHolder);\\n\\n /// @notice Emitted when Prime is changed\\n event NewPrime(address oldPrime, address newPrime);\\n\\n /// @notice Event emitted when VAI is minted\\n event MintVAI(address minter, uint256 mintVAIAmount);\\n\\n /// @notice Event emitted when VAI is repaid\\n event RepayVAI(address payer, address borrower, uint256 repayVAIAmount);\\n\\n /// @notice Event emitted when a borrow is liquidated\\n event LiquidateVAI(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n address vTokenCollateral,\\n uint256 seizeTokens\\n );\\n\\n /// @notice Emitted when treasury guardian is changed\\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\\n\\n /// @notice Emitted when treasury address is changed\\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\\n\\n /// @notice Emitted when treasury percent is changed\\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\\n\\n /// @notice Event emitted when VAIs are minted and fee are transferred\\n event MintFee(address minter, uint256 feeAmount);\\n\\n /// @notice Emiitted when VAI base rate is changed\\n event NewVAIBaseRate(uint256 oldBaseRateMantissa, uint256 newBaseRateMantissa);\\n\\n /// @notice Emiitted when VAI float rate is changed\\n event NewVAIFloatRate(uint256 oldFloatRateMantissa, uint256 newFlatRateMantissa);\\n\\n /// @notice Emiitted when VAI receiver address is changed\\n event NewVAIReceiver(address oldReceiver, address newReceiver);\\n\\n /// @notice Emiitted when VAI mint cap is changed\\n event NewVAIMintCap(uint256 oldMintCap, uint256 newMintCap);\\n\\n /// @notice Emitted when access control address is changed by admin\\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /// @notice Emitted when VAI token address is changed by admin\\n event NewVaiToken(address oldVaiToken, address newVaiToken);\\n\\n function initialize() external onlyAdmin {\\n require(vaiMintIndex == 0, \\\"already initialized\\\");\\n\\n vaiMintIndex = INITIAL_VAI_MINT_INDEX;\\n accrualBlockNumber = getBlockNumber();\\n mintCap = type(uint256).max;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n function _become(VAIUnitroller unitroller) external {\\n require(msg.sender == unitroller.admin(), \\\"only unitroller admin can change brains\\\");\\n require(unitroller._acceptImplementation() == 0, \\\"change not authorized\\\");\\n }\\n\\n /**\\n * @notice The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance.\\n * The amount minted must be less than the user's Account Liquidity and the mint vai limit.\\n * @dev If the Comptroller address is not set, minting is a no-op and the function returns the success code.\\n * @param mintVAIAmount The amount of the VAI to be minted.\\n * @return 0 on success, otherwise an error code\\n */\\n // solhint-disable-next-line code-complexity\\n function mintVAI(uint256 mintVAIAmount) external nonReentrant returns (uint256) {\\n if (address(comptroller) == address(0)) {\\n return uint256(Error.NO_ERROR);\\n }\\n\\n require(comptroller.userPoolId(msg.sender) == CORE_POOL_ID, \\\"VAI mint only allowed in the core Pool\\\");\\n\\n _ensureNonzeroAmount(mintVAIAmount);\\n _ensureNotPaused();\\n accrueVAIInterest();\\n\\n uint256 err;\\n address minter = msg.sender;\\n address _vai = vai;\\n uint256 vaiTotalSupply = IVAI(_vai).totalSupply();\\n\\n uint256 vaiNewTotalSupply = add_(vaiTotalSupply, mintVAIAmount);\\n require(vaiNewTotalSupply <= mintCap, \\\"mint cap reached\\\");\\n\\n _updateProtectionStateForEnteredMarkets(minter);\\n\\n uint256 accountMintableVAI;\\n (err, accountMintableVAI) = getMintableVAI(minter);\\n require(err == uint256(Error.NO_ERROR), \\\"could not compute mintable amount\\\");\\n\\n // check that user have sufficient mintableVAI balance\\n require(mintVAIAmount <= accountMintableVAI, \\\"minting more than allowed\\\");\\n\\n // Calculate the minted balance based on interest index\\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\\n\\n if (totalMintedVAI > 0) {\\n uint256 repayAmount = getVAIRepayAmount(minter);\\n uint256 remainedAmount = sub_(repayAmount, totalMintedVAI);\\n pastVAIInterest[minter] = add_(pastVAIInterest[minter], remainedAmount);\\n totalMintedVAI = repayAmount;\\n }\\n\\n uint256 accountMintVAINew = add_(totalMintedVAI, mintVAIAmount);\\n err = comptroller.setMintedVAIOf(minter, accountMintVAINew);\\n require(err == uint256(Error.NO_ERROR), \\\"comptroller rejection\\\");\\n\\n uint256 remainedAmount;\\n if (treasuryPercent != 0) {\\n uint256 feeAmount = div_(mul_(mintVAIAmount, treasuryPercent), 1e18);\\n remainedAmount = sub_(mintVAIAmount, feeAmount);\\n IVAI(_vai).mint(treasuryAddress, feeAmount);\\n\\n emit MintFee(minter, feeAmount);\\n } else {\\n remainedAmount = mintVAIAmount;\\n }\\n\\n IVAI(_vai).mint(minter, remainedAmount);\\n vaiMinterInterestIndex[minter] = vaiMintIndex;\\n\\n emit MintVAI(minter, remainedAmount);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice The repay function transfers VAI interest into the protocol and burns the rest,\\n * reducing the borrower's borrow balance. Before repaying VAI, users must first approve\\n * VAIController to access their VAI balance.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAI(uint256 amount) external nonReentrant returns (uint256, uint256) {\\n return _repayVAI(msg.sender, amount);\\n }\\n\\n /**\\n * @notice The repay on behalf function transfers VAI interest into the protocol and burns the rest,\\n * reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower).\\n * Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param borrower The account to repay the debt for.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAIBehalf(address borrower, uint256 amount) external nonReentrant returns (uint256, uint256) {\\n _ensureNonzeroAddress(borrower);\\n return _repayVAI(borrower, amount);\\n }\\n\\n /**\\n * @dev Checks the parameters and the protocol state, accrues interest, and invokes repayVAIFresh.\\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\\n * @param borrower The account to repay the debt for.\\n * @param amount The amount of VAI to be repaid.\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function _repayVAI(address borrower, uint256 amount) internal returns (uint256, uint256) {\\n if (address(comptroller) == address(0)) {\\n return (0, 0);\\n }\\n _ensureNonzeroAmount(amount);\\n _ensureNotPaused();\\n\\n accrueVAIInterest();\\n return repayVAIFresh(msg.sender, borrower, amount);\\n }\\n\\n /**\\n * @dev Repay VAI, expecting interest to be accrued\\n * @dev Borrowed VAIs are repaid by another user (possibly the borrower).\\n * @param payer the account paying off the VAI\\n * @param borrower the account with the debt being payed off\\n * @param repayAmount the amount of VAI being repaid\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function repayVAIFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256, uint256) {\\n (uint256 burn, uint256 partOfCurrentInterest, uint256 partOfPastInterest) = getVAICalculateRepayAmount(\\n borrower,\\n repayAmount\\n );\\n\\n IVAI _vai = IVAI(vai);\\n _vai.burn(payer, burn);\\n bool success = _vai.transferFrom(payer, receiver, partOfCurrentInterest);\\n require(success == true, \\\"failed to transfer VAI fee\\\");\\n\\n uint256 vaiBalanceBorrower = comptroller.mintedVAIs(borrower);\\n\\n uint256 accountVAINew = sub_(sub_(vaiBalanceBorrower, burn), partOfPastInterest);\\n pastVAIInterest[borrower] = sub_(pastVAIInterest[borrower], partOfPastInterest);\\n\\n uint256 error = comptroller.setMintedVAIOf(borrower, accountVAINew);\\n // We have to revert upon error since side-effects already happened at this point\\n require(error == uint256(Error.NO_ERROR), \\\"comptroller rejection\\\");\\n\\n uint256 repaidAmount = add_(burn, partOfCurrentInterest);\\n emit RepayVAI(payer, borrower, repaidAmount);\\n\\n return (uint256(Error.NO_ERROR), repaidAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of vai to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external nonReentrant returns (uint256, uint256) {\\n _ensureNotPaused();\\n\\n uint256 error = vTokenCollateral.accrueInterest();\\n if (error != uint256(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateVAIFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateVAIFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral by repay borrowers VAI.\\n * The collateral seized is transferred to the liquidator.\\n * @dev If the Comptroller address is not set, liquidation is a no-op and the function returns the success code.\\n * @param liquidator The address repaying the VAI and seizing collateral\\n * @param borrower The borrower of this VAI to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the VAI to repay\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\\n * @return Actual repayment amount\\n */\\n function liquidateVAIFresh(\\n address liquidator,\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint256, uint256) {\\n if (address(comptroller) != address(0)) {\\n accrueVAIInterest();\\n\\n /* Fail if liquidate not allowed */\\n uint256 allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n //if (vTokenCollateral.accrualBlockNumber() != accrualBlockNumber) {\\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayVAI fails */\\n (uint256 repayBorrowError, uint256 actualRepayAmount) = repayVAIFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint256(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateVAICalculateSeizeTokens(\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n require(\\n amountSeizeError == uint256(Error.NO_ERROR),\\n \\\"VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\"\\n );\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"VAI_LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n uint256 seizeError;\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint256(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateVAI(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint256(Error.NO_ERROR), actualRepayAmount);\\n }\\n }\\n\\n /*** Admin Functions ***/\\n\\n /**\\n * @notice Sets a new comptroller\\n * @dev Admin function to set a new comptroller\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setComptroller(ComptrollerInterface comptroller_) external returns (uint256) {\\n // Check caller is admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\\n }\\n\\n ComptrollerInterface oldComptroller = comptroller;\\n comptroller = comptroller_;\\n emit NewComptroller(oldComptroller, comptroller_);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Set the prime token contract address\\n * @param prime_ The new address of the prime token contract\\n */\\n function setPrimeToken(address prime_) external onlyAdmin {\\n emit NewPrime(prime, prime_);\\n prime = prime_;\\n }\\n\\n /**\\n * @notice Set the VAI token contract address\\n * @param vai_ The new address of the VAI token contract\\n */\\n function setVAIToken(address vai_) external onlyAdmin {\\n emit NewVaiToken(vai, vai_);\\n vai = vai_;\\n }\\n\\n /**\\n * @notice Toggle mint only for prime holder\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function toggleOnlyPrimeHolderMint() external returns (uint256) {\\n _ensureAllowed(\\\"toggleOnlyPrimeHolderMint()\\\");\\n\\n if (!mintEnabledOnlyForPrimeHolder && prime == address(0)) {\\n return uint256(Error.REJECTION);\\n }\\n\\n emit MintOnlyForPrimeHolder(mintEnabledOnlyForPrimeHolder, !mintEnabledOnlyForPrimeHolder);\\n mintEnabledOnlyForPrimeHolder = !mintEnabledOnlyForPrimeHolder;\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Local vars for avoiding stack-depth limits in calculating account total supply balance.\\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\\n */\\n struct AccountAmountLocalVars {\\n uint256 oErr;\\n MathError mErr;\\n uint256 sumSupply;\\n uint256 marketSupply;\\n uint256 sumBorrowPlusEffects;\\n uint256 vTokenBalance;\\n uint256 borrowBalance;\\n uint256 exchangeRateMantissa;\\n uint256 collateralPriceMantissa;\\n uint256 debtPriceMantissa;\\n Exp exchangeRate;\\n Exp collateralPrice;\\n Exp debtPrice;\\n Exp tokensToDenom;\\n }\\n\\n /**\\n * @notice Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate\\n * If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\\n * @param minter The account to check mintable VAI\\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\\n * @return Mintable amount (with 18 decimals)\\n */\\n // solhint-disable-next-line code-complexity\\n function getMintableVAI(address minter) public view returns (uint256, uint256) {\\n if (mintEnabledOnlyForPrimeHolder && !IPrime(prime).isUserPrimeHolder(minter)) {\\n return (uint256(Error.REJECTION), 0);\\n }\\n\\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\\n IDeviationBoundedOracle boundedOracle = comptroller.deviationBoundedOracle();\\n\\n AccountAmountLocalVars memory vars; // Holds all our calculation results\\n\\n uint256 accountMintableVAI;\\n uint256 i;\\n\\n /**\\n * We use this formula to calculate mintable VAI amount.\\n * totalSupplyAmount * VAIMintRate - (totalBorrowAmount + mintedVAIOf)\\n */\\n uint256 marketsCount = enteredMarkets.length;\\n for (i = 0; i < marketsCount; i++) {\\n (vars.oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = enteredMarkets[i]\\n .getAccountSnapshot(minter);\\n if (vars.oErr != 0) {\\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\\n return (uint256(Error.SNAPSHOT_ERROR), 0);\\n }\\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\\n\\n // Get bounded prices: collateral price for supply valuation, debt price for borrow valuation\\n (vars.collateralPriceMantissa, vars.debtPriceMantissa) = boundedOracle.getBoundedPricesView(\\n address(enteredMarkets[i])\\n );\\n if (vars.collateralPriceMantissa == 0 || vars.debtPriceMantissa == 0) {\\n return (uint256(Error.PRICE_ERROR), 0);\\n }\\n vars.collateralPrice = Exp({ mantissa: vars.collateralPriceMantissa });\\n vars.debtPrice = Exp({ mantissa: vars.debtPriceMantissa });\\n\\n (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.collateralPrice);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n // marketSupply = tokensToDenom * vTokenBalance\\n (vars.mErr, vars.marketSupply) = mulScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (, uint256 collateralFactorMantissa, , , , , ) = comptroller.markets(address(enteredMarkets[i]));\\n (vars.mErr, vars.marketSupply) = mulUInt(vars.marketSupply, collateralFactorMantissa);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, vars.marketSupply) = divUInt(vars.marketSupply, 1e18);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, vars.sumSupply) = addUInt(vars.sumSupply, vars.marketSupply);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n // sumBorrowPlusEffects += debtPrice * borrowBalance\\n (vars.mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(\\n vars.debtPrice,\\n vars.borrowBalance,\\n vars.sumBorrowPlusEffects\\n );\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n }\\n\\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\\n uint256 repayAmount = 0;\\n\\n if (totalMintedVAI > 0) {\\n repayAmount = getVAIRepayAmount(minter);\\n }\\n\\n (vars.mErr, vars.sumBorrowPlusEffects) = addUInt(vars.sumBorrowPlusEffects, repayAmount);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.MATH_ERROR), 0);\\n }\\n\\n (vars.mErr, accountMintableVAI) = mulUInt(vars.sumSupply, comptroller.vaiMintRate());\\n require(vars.mErr == MathError.NO_ERROR, \\\"VAI_MINT_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (vars.mErr, accountMintableVAI) = divUInt(accountMintableVAI, 10000);\\n require(vars.mErr == MathError.NO_ERROR, \\\"VAI_MINT_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (vars.mErr, accountMintableVAI) = subUInt(accountMintableVAI, vars.sumBorrowPlusEffects);\\n if (vars.mErr != MathError.NO_ERROR) {\\n return (uint256(Error.REJECTION), 0);\\n }\\n\\n return (uint256(Error.NO_ERROR), accountMintableVAI);\\n }\\n\\n /**\\n * @notice Update treasury data\\n * @param newTreasuryGuardian New Treasury Guardian address\\n * @param newTreasuryAddress New Treasury Address\\n * @param newTreasuryPercent New fee percentage for minting VAI that is sent to the treasury\\n */\\n function _setTreasuryData(\\n address newTreasuryGuardian,\\n address newTreasuryAddress,\\n uint256 newTreasuryPercent\\n ) external returns (uint256) {\\n // Check caller is admin\\n if (!(msg.sender == admin || msg.sender == treasuryGuardian)) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_TREASURY_OWNER_CHECK);\\n }\\n\\n require(newTreasuryPercent < 1e18, \\\"treasury percent cap overflow\\\");\\n\\n address oldTreasuryGuardian = treasuryGuardian;\\n address oldTreasuryAddress = treasuryAddress;\\n uint256 oldTreasuryPercent = treasuryPercent;\\n\\n treasuryGuardian = newTreasuryGuardian;\\n treasuryAddress = newTreasuryAddress;\\n treasuryPercent = newTreasuryPercent;\\n\\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Gets yearly VAI interest rate based on the VAI price\\n * @return uint256 Yearly VAI interest rate\\n */\\n function getVAIRepayRate() public view returns (uint256) {\\n ResilientOracleInterface oracle = comptroller.oracle();\\n MathError mErr;\\n\\n if (baseRateMantissa > 0) {\\n if (floatRateMantissa > 0) {\\n uint256 oraclePrice = oracle.getUnderlyingPrice(getVAIAddress());\\n if (1e18 > oraclePrice) {\\n uint256 delta;\\n uint256 rate;\\n\\n (mErr, delta) = subUInt(1e18, oraclePrice);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = mulUInt(delta, floatRateMantissa);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = divUInt(delta, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n (mErr, rate) = addUInt(delta, baseRateMantissa);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n return rate;\\n } else {\\n return baseRateMantissa;\\n }\\n } else {\\n return baseRateMantissa;\\n }\\n } else {\\n return 0;\\n }\\n }\\n\\n /**\\n * @notice Get interest rate per block\\n * @return uint256 Interest rate per bock\\n */\\n function getVAIRepayRatePerBlock() public view returns (uint256) {\\n uint256 yearlyRate = getVAIRepayRate();\\n\\n MathError mErr;\\n uint256 rate;\\n\\n (mErr, rate) = divUInt(yearlyRate, getBlocksPerYear());\\n require(mErr == MathError.NO_ERROR, \\\"VAI_REPAY_RATE_CALCULATION_FAILED\\\");\\n\\n return rate;\\n }\\n\\n /**\\n * @notice Get the last updated interest index for a VAI Minter\\n * @param minter Address of VAI minter\\n * @return uint256 Returns the interest rate index for a minter\\n */\\n function getVAIMinterInterestIndex(address minter) public view returns (uint256) {\\n uint256 storedIndex = vaiMinterInterestIndex[minter];\\n // If the user minted VAI before the stability fee was introduced, accrue\\n // starting from stability fee launch\\n if (storedIndex == 0) {\\n return INITIAL_VAI_MINT_INDEX;\\n }\\n return storedIndex;\\n }\\n\\n /**\\n * @notice Get the current total VAI a user needs to repay\\n * @param account The address of the VAI borrower\\n * @return (uint256) The total amount of VAI the user needs to repay\\n */\\n function getVAIRepayAmount(address account) public view returns (uint256) {\\n MathError mErr;\\n uint256 delta;\\n\\n uint256 amount = comptroller.mintedVAIs(account);\\n uint256 interest = pastVAIInterest[account];\\n uint256 totalMintedVAI;\\n uint256 newInterest;\\n\\n (mErr, totalMintedVAI) = subUInt(amount, interest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = subUInt(vaiMintIndex, getVAIMinterInterestIndex(account));\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, newInterest) = mulUInt(delta, totalMintedVAI);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, newInterest) = divUInt(newInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, amount) = addUInt(amount, newInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\\\");\\n\\n return amount;\\n }\\n\\n /**\\n * @notice Calculate how much VAI the user needs to repay\\n * @param borrower The address of the VAI borrower\\n * @param repayAmount The amount of VAI being returned\\n * @return Amount of VAI to be burned\\n * @return Amount of VAI the user needs to pay in current interest\\n * @return Amount of VAI the user needs to pay in past interest\\n */\\n function getVAICalculateRepayAmount(\\n address borrower,\\n uint256 repayAmount\\n ) public view returns (uint256, uint256, uint256) {\\n MathError mErr;\\n uint256 totalRepayAmount = getVAIRepayAmount(borrower);\\n uint256 currentInterest;\\n\\n (mErr, currentInterest) = subUInt(totalRepayAmount, comptroller.mintedVAIs(borrower));\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, currentInterest) = addUInt(pastVAIInterest[borrower], currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n uint256 burn;\\n uint256 partOfCurrentInterest = currentInterest;\\n uint256 partOfPastInterest = pastVAIInterest[borrower];\\n\\n if (repayAmount >= totalRepayAmount) {\\n (mErr, burn) = subUInt(totalRepayAmount, currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n } else {\\n uint256 delta;\\n\\n (mErr, delta) = mulUInt(repayAmount, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PART_CALCULATION_FAILED\\\");\\n\\n (mErr, delta) = divUInt(delta, totalRepayAmount);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PART_CALCULATION_FAILED\\\");\\n\\n uint256 totalMintedAmount;\\n (mErr, totalMintedAmount) = subUInt(totalRepayAmount, currentInterest);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_MINTED_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, burn) = mulUInt(totalMintedAmount, delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, burn) = divUInt(burn, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_BURN_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfCurrentInterest) = mulUInt(currentInterest, delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfCurrentInterest) = divUInt(partOfCurrentInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfPastInterest) = mulUInt(pastVAIInterest[borrower], delta);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PAST_INTEREST_CALCULATION_FAILED\\\");\\n\\n (mErr, partOfPastInterest) = divUInt(partOfPastInterest, 1e18);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_PAST_INTEREST_CALCULATION_FAILED\\\");\\n }\\n\\n return (burn, partOfCurrentInterest, partOfPastInterest);\\n }\\n\\n /**\\n * @notice Accrue interest on outstanding minted VAI\\n */\\n function accrueVAIInterest() public {\\n MathError mErr;\\n uint256 delta;\\n\\n (mErr, delta) = mulUInt(getVAIRepayRatePerBlock(), getBlockNumber() - accrualBlockNumber);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_INTEREST_ACCRUE_FAILED\\\");\\n\\n (mErr, delta) = addUInt(delta, vaiMintIndex);\\n require(mErr == MathError.NO_ERROR, \\\"VAI_INTEREST_ACCRUE_FAILED\\\");\\n\\n vaiMintIndex = delta;\\n accrualBlockNumber = getBlockNumber();\\n }\\n\\n /**\\n * @notice Sets the address of the access control of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlAddress New address for the access control\\n */\\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\\n _ensureNonzeroAddress(newAccessControlAddress);\\n\\n address oldAccessControlAddress = accessControl;\\n accessControl = newAccessControlAddress;\\n emit NewAccessControl(oldAccessControlAddress, accessControl);\\n }\\n\\n /**\\n * @notice Set VAI borrow base rate\\n * @param newBaseRateMantissa the base rate multiplied by 10**18\\n */\\n function setBaseRate(uint256 newBaseRateMantissa) external {\\n _ensureAllowed(\\\"setBaseRate(uint256)\\\");\\n\\n uint256 old = baseRateMantissa;\\n baseRateMantissa = newBaseRateMantissa;\\n emit NewVAIBaseRate(old, baseRateMantissa);\\n }\\n\\n /**\\n * @notice Set VAI borrow float rate\\n * @param newFloatRateMantissa the VAI float rate multiplied by 10**18\\n */\\n function setFloatRate(uint256 newFloatRateMantissa) external {\\n _ensureAllowed(\\\"setFloatRate(uint256)\\\");\\n\\n uint256 old = floatRateMantissa;\\n floatRateMantissa = newFloatRateMantissa;\\n emit NewVAIFloatRate(old, floatRateMantissa);\\n }\\n\\n /**\\n * @notice Set VAI stability fee receiver address\\n * @param newReceiver the address of the VAI fee receiver\\n */\\n function setReceiver(address newReceiver) external onlyAdmin {\\n _ensureNonzeroAddress(newReceiver);\\n\\n address old = receiver;\\n receiver = newReceiver;\\n emit NewVAIReceiver(old, newReceiver);\\n }\\n\\n /**\\n * @notice Set VAI mint cap\\n * @param _mintCap the amount of VAI that can be minted\\n */\\n function setMintCap(uint256 _mintCap) external {\\n _ensureAllowed(\\\"setMintCap(uint256)\\\");\\n\\n uint256 old = mintCap;\\n mintCap = _mintCap;\\n emit NewVAIMintCap(old, _mintCap);\\n }\\n\\n function getBlockNumber() internal view virtual returns (uint256) {\\n return block.number;\\n }\\n\\n function getBlocksPerYear() public view virtual returns (uint256) {\\n return 70080000; //(24 * 60 * 60 * 365) / 0.45;\\n }\\n\\n /**\\n * @notice Return the address of the VAI token\\n * @return The address of VAI\\n */\\n function getVAIAddress() public view virtual returns (address) {\\n return vai;\\n }\\n\\n modifier onlyAdmin() {\\n require(msg.sender == admin, \\\"only admin can\\\");\\n _;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n function _ensureAllowed(string memory functionSig) private view {\\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \\\"access denied\\\");\\n }\\n\\n /// @dev Reverts if the protocol is paused\\n function _ensureNotPaused() private view {\\n require(!comptroller.protocolPaused(), \\\"protocol is paused\\\");\\n }\\n\\n /// @dev Reverts if the passed address is zero\\n function _ensureNonzeroAddress(address someone) private pure {\\n require(someone != address(0), \\\"can't be zero address\\\");\\n }\\n\\n /// @dev Reverts if the passed amount is zero\\n function _ensureNonzeroAmount(uint256 amount) private pure {\\n require(amount > 0, \\\"amount can't be zero\\\");\\n }\\n\\n /// @dev Persists the DBO protection window for every market the minter has entered, so VAI minting\\n /// records the same on-chain price history as the borrow path. Extracted from `mintVAI` to avoid\\n /// stack-too-deep in that function.\\n function _updateProtectionStateForEnteredMarkets(address minter) private {\\n IDeviationBoundedOracle dbo = comptroller.deviationBoundedOracle();\\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\\n uint256 enteredLength = enteredMarkets.length;\\n for (uint256 i; i < enteredLength; ++i) {\\n dbo.updateProtectionState(address(enteredMarkets[i]));\\n }\\n }\\n}\\n\",\"keccak256\":\"0x830579a0fc7a1b46296f1b647cfa70b63dba40018429731b1bab6812f32fb745\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerInterface.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { VTokenInterface } from \\\"../VTokens/VTokenInterfaces.sol\\\";\\n\\ninterface VAIControllerInterface {\\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\\n\\n function repayVAI(uint256 amount) external returns (uint256, uint256);\\n\\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\\n\\n function liquidateVAI(\\n address borrower,\\n uint256 repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint256, uint256);\\n\\n function getMintableVAI(address minter) external view returns (uint256, uint256);\\n\\n function getVAIAddress() external view returns (address);\\n\\n function getVAIRepayAmount(address account) external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x69d2f9e13b7fbf0a29885048503642372d9ba3d37f2427d4b9cffb87eddd925b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIControllerStorage.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\n\\ncontract VAIUnitrollerAdminStorage {\\n /**\\n * @notice Administrator for this contract\\n */\\n address public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address public pendingAdmin;\\n\\n /**\\n * @notice Active brains of Unitroller\\n */\\n address public vaiControllerImplementation;\\n\\n /**\\n * @notice Pending brains of Unitroller\\n */\\n address public pendingVAIControllerImplementation;\\n}\\n\\ncontract VAIControllerStorageG1 is VAIUnitrollerAdminStorage {\\n ComptrollerInterface public comptroller;\\n\\n struct VenusVAIState {\\n /// @notice The last updated venusVAIMintIndex\\n uint224 index;\\n /// @notice The block number the index was last updated at\\n uint32 block;\\n }\\n\\n /// @notice The Venus VAI state\\n VenusVAIState public venusVAIState;\\n\\n /// @notice The Venus VAI state initialized\\n bool public isVenusVAIInitialized;\\n\\n /// @notice The Venus VAI minter index as of the last time they accrued XVS\\n mapping(address => uint256) public venusVAIMinterIndex;\\n}\\n\\ncontract VAIControllerStorageG2 is VAIControllerStorageG1 {\\n /// @notice Treasury Guardian address\\n address public treasuryGuardian;\\n\\n /// @notice Treasury address\\n address public treasuryAddress;\\n\\n /// @notice Fee percent of accrued interest with decimal 18\\n uint256 public treasuryPercent;\\n\\n /// @notice Guard variable for re-entrancy checks\\n bool internal _notEntered;\\n\\n /// @notice The base rate for stability fee\\n uint256 public baseRateMantissa;\\n\\n /// @notice The float rate for stability fee\\n uint256 public floatRateMantissa;\\n\\n /// @notice The address for VAI interest receiver\\n address public receiver;\\n\\n /// @notice Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\\n uint256 public vaiMintIndex;\\n\\n /// @notice Block number that interest was last accrued at\\n uint256 internal accrualBlockNumber;\\n\\n /// @notice Global vaiMintIndex as of the most recent balance-changing action for user\\n mapping(address => uint256) internal vaiMinterInterestIndex;\\n\\n /// @notice Tracks the amount of mintedVAI of a user that represents the accrued interest\\n mapping(address => uint256) public pastVAIInterest;\\n\\n /// @notice VAI mint cap\\n uint256 public mintCap;\\n\\n /// @notice Access control manager address\\n address public accessControl;\\n}\\n\\ncontract VAIControllerStorageG3 is VAIControllerStorageG2 {\\n /// @notice The address of the prime contract. It can be a ZERO address\\n address public prime;\\n\\n /// @notice Tracks if minting is enabled only for prime token holders. Only used if prime is set\\n bool public mintEnabledOnlyForPrimeHolder;\\n}\\n\\ncontract VAIControllerStorageG4 is VAIControllerStorageG3 {\\n /// @notice The address of the VAI token\\n address internal vai;\\n}\\n\",\"keccak256\":\"0x75295c0c9d1e5e7b8726b0d43c260975eb4d8d0b76325360c39723b996b95603\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VAI/VAIUnitroller.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { VAIControllerErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { VAIUnitrollerAdminStorage } from \\\"./VAIControllerStorage.sol\\\";\\n\\n/**\\n * @title VAI Unitroller\\n * @author Venus\\n * @notice This is the proxy contract for the VAIComptroller\\n */\\ncontract VAIUnitroller is VAIUnitrollerAdminStorage, VAIControllerErrorReporter {\\n /**\\n * @notice Emitted when pendingVAIControllerImplementation is changed\\n */\\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\\n\\n /**\\n * @notice Emitted when pendingVAIControllerImplementation is accepted, which means comptroller implementation is updated\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n constructor() {\\n // Set admin to caller\\n admin = msg.sender;\\n }\\n\\n /*** Admin Functions ***/\\n function _setPendingImplementation(address newPendingImplementation) public returns (uint256) {\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\\n }\\n\\n address oldPendingImplementation = pendingVAIControllerImplementation;\\n\\n pendingVAIControllerImplementation = newPendingImplementation;\\n\\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\\n * @dev Admin function for new implementation to accept it's role as implementation\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptImplementation() public returns (uint256) {\\n // Check caller is pendingImplementation\\n if (msg.sender != pendingVAIControllerImplementation) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldImplementation = vaiControllerImplementation;\\n address oldPendingImplementation = pendingVAIControllerImplementation;\\n\\n vaiControllerImplementation = pendingVAIControllerImplementation;\\n\\n pendingVAIControllerImplementation = address(0);\\n\\n emit NewImplementation(oldImplementation, vaiControllerImplementation);\\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _setPendingAdmin(address newPendingAdmin) public returns (uint256) {\\n // Check caller = admin\\n if (msg.sender != admin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\\n }\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\\n */\\n function _acceptAdmin() public returns (uint256) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = address(0);\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint256(Error.NO_ERROR);\\n }\\n\\n /**\\n * @dev Delegates execution to an implementation contract.\\n * It returns to the external caller whatever the implementation returns\\n * or forwards reverts.\\n */\\n fallback() external {\\n // delegate all other functions to current implementation\\n (bool success, ) = vaiControllerImplementation.delegatecall(msg.data);\\n\\n assembly {\\n let free_mem_ptr := mload(0x40)\\n returndatacopy(free_mem_ptr, 0, returndatasize())\\n\\n switch success\\n case 0 {\\n revert(free_mem_ptr, returndatasize())\\n }\\n default {\\n return(free_mem_ptr, returndatasize())\\n }\\n }\\n }\\n}\\n\",\"keccak256\":\"0xfe33306ad442bbfe51c50572f91005d98cb657649316ca29aa650fa679dbca86\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VToken.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { IAccessControlManagerV8 } from \\\"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\\\";\\nimport { IProtocolShareReserve } from \\\"../../external/IProtocolShareReserve.sol\\\";\\nimport { ComptrollerInterface, IComptroller } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { TokenErrorReporter } from \\\"../../Utils/ErrorReporter.sol\\\";\\nimport { Exponential } from \\\"../../Utils/Exponential.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\nimport { VTokenInterface } from \\\"./VTokenInterfaces.sol\\\";\\nimport { MANTISSA_ONE } from \\\"@venusprotocol/solidity-utilities/contracts/constants.sol\\\";\\n\\n/**\\n * @title Venus's vToken Contract\\n * @notice Abstract base for vTokens\\n * @author Venus\\n */\\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\\n struct MintLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint mintTokens;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n uint actualMintAmount;\\n }\\n\\n struct RedeemLocalVars {\\n MathError mathErr;\\n uint exchangeRateMantissa;\\n uint redeemTokens;\\n uint redeemAmount;\\n uint totalSupplyNew;\\n uint accountTokensNew;\\n }\\n\\n struct BorrowLocalVars {\\n MathError mathErr;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n }\\n\\n struct RepayBorrowLocalVars {\\n Error err;\\n MathError mathErr;\\n uint repayAmount;\\n uint borrowerIndex;\\n uint accountBorrows;\\n uint accountBorrowsNew;\\n uint totalBorrowsNew;\\n uint actualRepayAmount;\\n }\\n\\n /*** Reentrancy Guard ***/\\n\\n /**\\n * @dev Prevents a contract from calling itself, directly or indirectly.\\n */\\n modifier nonReentrant() {\\n require(_notEntered, \\\"re-entered\\\");\\n _notEntered = false;\\n _;\\n _notEntered = true; // get a gas-refund post-Istanbul\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Transfer `amount` tokens from `src` to `dst`\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param amount The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n // @custom:event Emits Transfer event\\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Approve `spender` to transfer up to `amount` from `src`\\n * @dev This will overwrite the approval amount for `spender`\\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\\n * @param spender The address of the account which may transfer tokens\\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\\n * @return Whether or not the approval succeeded\\n */\\n // @custom:event Emits Approval event on successful approve\\n function approve(address spender, uint256 amount) external override returns (bool) {\\n transferAllowances[msg.sender][spender] = amount;\\n emit Approval(msg.sender, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @notice Get the underlying balance of the `owner`\\n * @dev This also accrues interest in a transaction\\n * @param owner The address of the account to query\\n * @return The amount of underlying owned by `owner`\\n */\\n function balanceOfUnderlying(address owner) external override returns (uint) {\\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\\n ensureNoMathError(mErr);\\n return balance;\\n }\\n\\n /**\\n * @notice Returns the current total borrows plus accrued interest\\n * @return The total borrows with interest\\n */\\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return totalBorrows;\\n }\\n\\n /**\\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\\n * @param account The address whose balance should be calculated after updating borrowIndex\\n * @return The calculated balance\\n */\\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return borrowBalanceStored(account);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Will fail unless called by another vToken during the process of liquidation.\\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits Transfer event\\n function seize(\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) external override nonReentrant returns (uint) {\\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\\n }\\n\\n /**\\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\\n * @param newPendingAdmin New pending admin.\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\\n // Check caller = admin\\n ensureAdmin(msg.sender);\\n\\n // Save current value, if any, for inclusion in log\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store pendingAdmin with value newPendingAdmin\\n pendingAdmin = newPendingAdmin;\\n\\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\\n * @dev Admin function for pending admin to accept role and update admin\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewAdmin event on successful acceptance\\n // @custom:event Emits NewPendingAdmin event with null new pending admin\\n function _acceptAdmin() external override returns (uint) {\\n // Check caller is pendingAdmin\\n if (msg.sender != pendingAdmin) {\\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\\n }\\n\\n // Save current values for inclusion in log\\n address oldAdmin = admin;\\n address oldPendingAdmin = pendingAdmin;\\n\\n // Store admin with value pendingAdmin\\n admin = pendingAdmin;\\n\\n // Clear the pending value\\n pendingAdmin = payable(address(0));\\n\\n emit NewAdmin(oldAdmin, admin);\\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\\n * @dev Governor function to accrue interest and set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewReserveFactor event\\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_setReserveFactor(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\\n return _setReserveFactorFresh(newReserveFactorMantissa_);\\n }\\n\\n /**\\n * @notice Sets the address of the access control manager of this contract\\n * @dev Admin function to set the access control address\\n * @param newAccessControlManagerAddress New address for the access control\\n * @return uint 0=success, otherwise will revert\\n */\\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n ensureNonZeroAddress(newAccessControlManagerAddress);\\n\\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\\n accessControlManager = newAccessControlManagerAddress;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\\n * @param reduceAmount_ Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits ReservesReduced event\\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\\n ensureAllowed(\\\"_reduceReserves(uint256)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // If reserves were reduced in accrueInterest\\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\\n return _reduceReservesFresh(reduceAmount_);\\n }\\n\\n /**\\n * @notice Get the current allowance from `owner` for `spender`\\n * @param owner The address of the account which owns the tokens to be spent\\n * @param spender The address of the account which may transfer tokens\\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\\n */\\n function allowance(address owner, address spender) external view override returns (uint256) {\\n return transferAllowances[owner][spender];\\n }\\n\\n /**\\n * @notice Get the token balance of the `owner`\\n * @param owner The address of the account to query\\n * @return The number of tokens owned by `owner`\\n */\\n function balanceOf(address owner) external view override returns (uint256) {\\n return accountTokens[owner];\\n }\\n\\n /**\\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\\n * @param account Address of the account to snapshot\\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\\n */\\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\\n uint borrowBalance;\\n uint exchangeRateMantissa;\\n\\n MathError mErr;\\n\\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (mErr != MathError.NO_ERROR) {\\n return (uint(Error.MATH_ERROR), 0, 0, 0);\\n }\\n\\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\\n }\\n\\n /**\\n * @notice Returns the current per-block supply interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The supply interest rate per block, scaled by 1e18\\n */\\n function supplyRatePerBlock() external view override returns (uint) {\\n return\\n interestRateModel.getSupplyRate(\\n _getCashPriorWithFlashLoan(),\\n totalBorrows,\\n totalReserves,\\n reserveFactorMantissa\\n );\\n }\\n\\n /**\\n * @notice Returns the current per-block borrow interest rate for this vToken\\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\\n * @return The borrow interest rate per block, scaled by 1e18\\n */\\n function borrowRatePerBlock() external view override returns (uint) {\\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\\n }\\n\\n /**\\n * @notice Get cash balance of this vToken in the underlying asset\\n * @return The quantity of underlying asset owned by this contract\\n */\\n function getCash() external view override returns (uint) {\\n return getCashPrior();\\n }\\n\\n /**\\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\\n * @param newReduceReservesBlockDelta_ block difference value\\n */\\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\\n require(newReduceReservesBlockDelta_ > 0, \\\"Invalid Input\\\");\\n ensureAllowed(\\\"setReduceReservesBlockDelta(uint256)\\\");\\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\\n }\\n\\n /**\\n * @notice Sets protocol share reserve contract address\\n * @param protcolShareReserve_ The address of protocol share reserve contract\\n */\\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n ensureNonZeroAddress(protcolShareReserve_);\\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\\n protocolShareReserve = protcolShareReserve_;\\n }\\n\\n /**\\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferOut` internal function.\\n * - The caller must be the Comptroller contract.\\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\\n * @param to The address to which the underlying asset is to be transferred.\\n * @param amount The amount of the underlying asset to transfer.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\\n */\\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n if (flashLoanAmount > 0) {\\n revert FlashLoanAlreadyActive();\\n }\\n\\n if (getCashPrior() < amount) {\\n revert InsufficientCash();\\n }\\n flashLoanAmount = amount;\\n doTransferOut(to, amount);\\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\\n }\\n\\n /**\\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\\n * - The caller must be the Comptroller contract.\\n * - Transfers the protocol fee to the protocol share reserve.\\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\\n * @param from The address from which the underlying asset is to be transferred.\\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\\n * @param totalFee The total fee amount for the flash loan.\\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\\n */\\n function transferInUnderlyingFlashLoan(\\n address payable from,\\n uint256 repaymentAmount,\\n uint256 totalFee,\\n uint256 protocolFee\\n ) external nonReentrant returns (uint256) {\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\\n\\n if (actualAmountTransferred < totalFee) {\\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\\n }\\n\\n // Transfer protocol fee to protocol share reserve\\n doTransferOut(protocolShareReserve, protocolFee);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.FLASHLOAN\\n );\\n\\n // Reset flashLoanAmount to complete the flash loan cycle\\n flashLoanAmount = 0;\\n\\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\\n return actualAmountTransferred;\\n }\\n\\n /**\\n * @notice Sets flash loan status for the market\\n * @param enabled True to enable flash loans, false to disable\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:event Emits FlashLoanStatusChanged event on success\\n */\\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanEnabled(bool)\\\");\\n\\n if (isFlashLoanEnabled != enabled) {\\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\\n isFlashLoanEnabled = enabled;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Update flashLoan fee mantissa\\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:access Only Governance\\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\\n * @custom:event Emits FlashLoanFeeUpdated event on success\\n */\\n function setFlashLoanFeeMantissa(\\n uint256 flashLoanFeeMantissa_,\\n uint256 flashLoanProtocolShare_\\n ) external returns (uint256) {\\n ensureAllowed(\\\"setFlashLoanFeeMantissa(uint256,uint256)\\\");\\n\\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\\n }\\n\\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\\n }\\n\\n // Only proceed if values are changing\\n if (\\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\\n ) {\\n emit FlashLoanFeeUpdated(\\n flashLoanFeeMantissa,\\n flashLoanFeeMantissa_,\\n flashLoanProtocolShareMantissa,\\n flashLoanProtocolShare_\\n );\\n\\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\\n }\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Initialize the money market\\n * @param comptroller_ The address of the Comptroller\\n * @param interestRateModel_ The address of the interest rate model\\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\\n * @param name_ EIP-20 name of this token\\n * @param symbol_ EIP-20 symbol of this token\\n * @param decimals_ EIP-20 decimal precision of this token\\n */\\n function initialize(\\n ComptrollerInterface comptroller_,\\n InterestRateModelV8 interestRateModel_,\\n uint initialExchangeRateMantissa_,\\n string memory name_,\\n string memory symbol_,\\n uint8 decimals_\\n ) public {\\n ensureAdmin(msg.sender);\\n require(accrualBlockNumber == 0 && borrowIndex == 0, \\\"market may only be initialized once\\\");\\n\\n // Set initial exchange rate\\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\\n require(initialExchangeRateMantissa > 0, \\\"initial exchange rate must be greater than zero.\\\");\\n\\n // Set the comptroller\\n uint err = _setComptroller(comptroller_);\\n require(err == uint(Error.NO_ERROR), \\\"setting comptroller failed\\\");\\n\\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\\n accrualBlockNumber = block.number;\\n borrowIndex = mantissaOne;\\n\\n // Set the interest rate model (depends on block number / borrow index)\\n err = _setInterestRateModelFresh(interestRateModel_);\\n require(err == uint(Error.NO_ERROR), \\\"setting interest rate model failed\\\");\\n\\n name = name_;\\n symbol = symbol_;\\n decimals = decimals_;\\n\\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\\n _notEntered = true;\\n }\\n\\n /**\\n * @notice Accrue interest then return the up-to-date exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\\n require(accrueInterest() == uint(Error.NO_ERROR), \\\"accrue interest failed\\\");\\n return exchangeRateStored();\\n }\\n\\n /**\\n * @notice Applies accrued interest to total borrows and reserves\\n * @dev This calculates interest accrued from the last checkpointed block\\n * up to the current block and writes new checkpoint to storage and\\n * reduce spread reserves to protocol share reserve\\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\\n */\\n // @custom:event Emits AccrueInterest event\\n function accrueInterest() public virtual override returns (uint) {\\n /* Remember the initial block number */\\n uint currentBlockNumber = block.number;\\n uint accrualBlockNumberPrior = accrualBlockNumber;\\n\\n /* Short-circuit accumulating 0 interest */\\n if (accrualBlockNumberPrior == currentBlockNumber) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n /* Read the previous values out of storage */\\n uint cashPrior = _getCashPriorWithFlashLoan();\\n uint borrowsPrior = totalBorrows;\\n uint reservesPrior = totalReserves;\\n uint borrowIndexPrior = borrowIndex;\\n\\n /* Calculate the current borrow interest rate */\\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\\n require(borrowRateMantissa <= borrowRateMaxMantissa, \\\"borrow rate is absurdly high\\\");\\n\\n /* Calculate the number of blocks elapsed since the last accrual */\\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\\n ensureNoMathError(mathErr);\\n\\n /*\\n * Calculate the interest accumulated into borrows and reserves and the new index:\\n * simpleInterestFactor = borrowRate * blockDelta\\n * interestAccumulated = simpleInterestFactor * totalBorrows\\n * totalBorrowsNew = interestAccumulated + totalBorrows\\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\\n */\\n\\n Exp memory simpleInterestFactor;\\n uint interestAccumulated;\\n uint totalBorrowsNew;\\n uint totalReservesNew;\\n uint borrowIndexNew;\\n\\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\\n Exp({ mantissa: reserveFactorMantissa }),\\n interestAccumulated,\\n reservesPrior\\n );\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\\n if (mathErr != MathError.NO_ERROR) {\\n return\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n uint(mathErr)\\n );\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accrualBlockNumber = currentBlockNumber;\\n borrowIndex = borrowIndexNew;\\n totalBorrows = totalBorrowsNew;\\n totalReserves = totalReservesNew;\\n\\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\\n ensureNoMathError(mathErr);\\n if (blockDelta >= reduceReservesBlockDelta) {\\n reduceReservesBlockNumber = currentBlockNumber;\\n uint actualCash = getCashPrior();\\n if (actualCash < totalReservesNew) {\\n _reduceReservesFresh(actualCash);\\n } else {\\n _reduceReservesFresh(totalReservesNew);\\n }\\n }\\n\\n /* We emit an AccrueInterest event */\\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new comptroller for the market\\n * @dev Admin function to set a new comptroller\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // @custom:event Emits NewComptroller event\\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\\n // Check caller is admin\\n ensureAdmin(msg.sender);\\n\\n // Ensure invoke comptroller.isComptroller() returns true\\n require(newComptroller.isComptroller(), \\\"marker method returned false\\\");\\n\\n // Emit NewComptroller(oldComptroller, newComptroller)\\n emit NewComptroller(comptroller, newComptroller);\\n\\n // Set market's comptroller to newComptroller\\n comptroller = newComptroller;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\\n * @dev Governance function to accrue interest and update the interest rate model\\n * @param newInterestRateModel_ The new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\\n ensureAllowed(\\\"_setInterestRateModel(address)\\\");\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\\n return _setInterestRateModelFresh(newInterestRateModel_);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the VToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStored() public view override returns (uint) {\\n (MathError err, uint result) = exchangeRateStoredInternal();\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return The calculated balance\\n */\\n function borrowBalanceStored(address account) public view override returns (uint) {\\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\\n ensureNoMathError(err);\\n return result;\\n }\\n\\n /**\\n * @notice Opens a debt position for the borrower as part of flash loan repayment\\n * @dev This function is specifically called during flash loan operations when the repayment\\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\\n * and updates the borrower's balance. It also emits a Borrow event and calls the\\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\\n * if the market's block number is not current.\\n * @param borrower The address of the borrower who will have the debt position created\\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\\n */\\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\\n // Reverts if the caller is not the comptroller\\n if (msg.sender != address(comptroller)) {\\n revert InvalidComptroller();\\n }\\n\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors.\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\\n }\\n\\n /**\\n * @notice Calculates the total fee and protocol fee for a flash loan..\\n * @param amount The amount of the flash loan.\\n * @return totalFee The total fee for the flash loan.\\n * @return protocolFee The portion of the total fee allocated to the protocol.\\n */\\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\\n MathError mErr;\\n uint256 totalFee;\\n uint256 protocolFee;\\n\\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\\n ensureNoMathError(mErr);\\n\\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\\n ensureNoMathError(mErr);\\n\\n return (totalFee, protocolFee);\\n }\\n\\n /**\\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\\n * @dev Called by both `transfer` and `transferFrom` internally\\n * @param spender The address of the account performing the transfer\\n * @param src The address of the source account\\n * @param dst The address of the destination account\\n * @param tokens The number of tokens to transfer\\n * @return Whether or not the transfer succeeded\\n */\\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\\n /* Fail if transfer not allowed */\\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Do not allow self-transfers */\\n if (src == dst) {\\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n /* Get the allowance, infinite for the account owner */\\n uint startingAllowance = 0;\\n if (spender == src) {\\n startingAllowance = type(uint256).max;\\n } else {\\n startingAllowance = transferAllowances[src][spender];\\n }\\n\\n /* Do the calculations, checking for {under,over}flow */\\n MathError mathErr;\\n uint allowanceNew;\\n uint srvTokensNew;\\n uint dstTokensNew;\\n\\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\\n }\\n\\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\\n }\\n\\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n accountTokens[src] = srvTokensNew;\\n accountTokens[dst] = dstTokensNew;\\n\\n /* Eat some of the allowance (if necessary) */\\n if (startingAllowance != type(uint256).max) {\\n transferAllowances[src][spender] = allowanceNew;\\n }\\n\\n /* We emit a Transfer event */\\n emit Transfer(src, dst, tokens);\\n\\n comptroller.transferVerify(address(this), src, dst, tokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintFresh(msg.sender, mintAmount);\\n }\\n\\n /**\\n * @notice User supplies assets into the market and receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param minter The address of the account which is supplying the assets\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the minter and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[minter] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[minter] = vars.accountTokensNew;\\n\\n /* We emit a Mint event, and a Transfer event */\\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), minter, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param receiver The address of the account which is receiving the vTokens\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\\n }\\n\\n /**\\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param payer The address of the account which is paying the underlying token\\n * @param receiver The address of the account which is receiving vToken\\n * @param mintAmount The amount of the underlying asset to supply\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\\n */\\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\\n ensureNonZeroAddress(receiver);\\n /* Fail if mint not allowed */\\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\\n }\\n\\n MintLocalVars memory vars;\\n\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call `doTransferIn` for the payer and the mintAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\\n * side-effects occurred. The function returns the amount actually transferred,\\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\\n * of cash.\\n */\\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\\n\\n /*\\n * We get the current exchange rate and calculate the number of vTokens to be minted:\\n * mintTokens = actualMintAmount / exchangeRate\\n */\\n\\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\\n vars.actualMintAmount,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n /*\\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\\n * totalSupplyNew = totalSupply + mintTokens\\n * accountTokensNew = accountTokens[receiver] + mintTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[receiver] = vars.accountTokensNew;\\n\\n /* We emit a MintBehalf event, and a Transfer event */\\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\\n emit Transfer(address(this), receiver, vars.mintTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\\n\\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokens The number of vTokens to redeem into underlying\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokens\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\\n }\\n\\n /**\\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens, if called by a delegate\\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function redeemUnderlyingInternal(\\n address redeemer,\\n address payable receiver,\\n uint redeemAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\\n }\\n\\n /**\\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\\n * @dev Assumes interest has already been accrued up to the current block\\n * @param redeemer The address of the account which is redeeming the tokens\\n * @param receiver The receiver of the tokens\\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n // solhint-disable-next-line code-complexity\\n function redeemFresh(\\n address redeemer,\\n address payable receiver,\\n uint redeemTokensIn,\\n uint redeemAmountIn\\n ) internal returns (uint) {\\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \\\"one of redeemTokensIn or redeemAmountIn must be zero\\\");\\n\\n RedeemLocalVars memory vars;\\n\\n /* exchangeRate = invoke Exchange Rate Stored() */\\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\\n ensureNoMathError(vars.mathErr);\\n\\n /* If redeemTokensIn > 0: */\\n if (redeemTokensIn > 0) {\\n /*\\n * We calculate the exchange rate and the amount of underlying to be redeemed:\\n * redeemTokens = redeemTokensIn\\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\\n */\\n vars.redeemTokens = redeemTokensIn;\\n\\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\\n Exp({ mantissa: vars.exchangeRateMantissa }),\\n redeemTokensIn\\n );\\n ensureNoMathError(vars.mathErr);\\n } else {\\n /*\\n * We get the current exchange rate and calculate the amount to be redeemed:\\n * redeemTokens = redeemAmountIn / exchangeRate\\n * redeemAmount = redeemAmountIn\\n */\\n\\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\\n redeemAmountIn,\\n Exp({ mantissa: vars.exchangeRateMantissa })\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n vars.redeemAmount = redeemAmountIn;\\n }\\n\\n /* Fail if redeem not allowed */\\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /*\\n * We calculate the new total supply and redeemer balance, checking for underflow:\\n * totalSupplyNew = totalSupply - redeemTokens\\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\\n */\\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\\n ensureNoMathError(vars.mathErr);\\n\\n /* Fail gracefully if protocol has insufficient cash */\\n if (getCashPrior() < vars.redeemAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write previously calculated values into storage */\\n totalSupply = vars.totalSupplyNew;\\n accountTokens[redeemer] = vars.accountTokensNew;\\n\\n /*\\n * We invoke doTransferOut for the receiver and the redeemAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken has redeemAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n\\n uint feeAmount;\\n uint remainedAmount;\\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\\n (vars.mathErr, feeAmount) = mulUInt(\\n vars.redeemAmount,\\n IComptroller(address(comptroller)).treasuryPercent()\\n );\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\\n doTransferOut(treasuryAddress, feeAmount);\\n\\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\\n } else {\\n remainedAmount = vars.redeemAmount;\\n }\\n\\n doTransferOut(receiver, remainedAmount);\\n\\n /* We emit a Transfer event, and a Redeem event */\\n emit Transfer(redeemer, address(this), vars.redeemTokens);\\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function borrowInternal(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount\\n ) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\\n return borrowFresh(borrower, receiver, borrowAmount, true);\\n }\\n\\n /**\\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\\n * @dev Before calling this function, ensure that the interest has been accrued\\n * @param borrower The borrower, on behalf of whom to borrow\\n * @param receiver The account that would receive the funds (can be the same as the borrower)\\n * @param borrowAmount The amount of the underlying asset to borrow\\n * @param shouldTransfer Whether to call doTransferOut for the receiver\\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\\n */\\n function borrowFresh(\\n address borrower,\\n address payable receiver,\\n uint borrowAmount,\\n bool shouldTransfer\\n ) internal returns (uint) {\\n /* Revert if borrow not allowed */\\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\\n\\n if (allowed != 0) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n revert(\\\"math error\\\");\\n }\\n\\n /* Revert if protocol has insufficient underlying cash */\\n if (shouldTransfer && getCashPrior() < borrowAmount) {\\n revert(\\\"math error\\\");\\n }\\n\\n BorrowLocalVars memory vars;\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on overflow:\\n * accountBorrowsNew = accountBorrows + borrowAmount\\n * totalBorrowsNew = totalBorrows + borrowAmount\\n */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n if (shouldTransfer) {\\n /*\\n * We invoke doTransferOut for the receiver and the borrowAmount.\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken borrowAmount less of cash.\\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n */\\n doTransferOut(receiver, borrowAmount);\\n }\\n\\n /* We emit a Borrow event */\\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sender repays their own borrow\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\\n }\\n\\n /**\\n * @notice Sender repays a borrow belonging to another borrowing account\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\\n }\\n\\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\\n }\\n\\n /**\\n * @notice Borrows are repaid by another user (possibly the borrower).\\n * @param payer The account paying off the borrow\\n * @param borrower The account with the debt being payed off\\n * @param repayAmount The amount of undelrying tokens being returned\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\\n /* Fail if repayBorrow not allowed */\\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\\n if (allowed != 0) {\\n return (\\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\\n 0\\n );\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\\n }\\n\\n RepayBorrowLocalVars memory vars;\\n\\n /* We remember the original borrowerIndex for verification purposes */\\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\\n\\n /* We fetch the amount the borrower owes, with accumulated interest */\\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\\n if (vars.mathErr != MathError.NO_ERROR) {\\n return (\\n failOpaque(\\n Error.MATH_ERROR,\\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n uint(vars.mathErr)\\n ),\\n 0\\n );\\n }\\n\\n // caps the repayAmount to the actual owed amount\\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the payer and the repayAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional repayAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\\n\\n /*\\n * We calculate the new borrower and total borrow balances, failing on underflow:\\n * accountBorrowsNew = accountBorrows - actualRepayAmount\\n * totalBorrowsNew = totalBorrows - actualRepayAmount\\n */\\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\\n ensureNoMathError(vars.mathErr);\\n\\n /* We write the previously calculated values into storage */\\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\\n accountBorrows[borrower].interestIndex = borrowIndex;\\n totalBorrows = vars.totalBorrowsNew;\\n\\n /* We emit a RepayBorrow event */\\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\\n\\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\\n }\\n\\n /**\\n * @notice The sender liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n function liquidateBorrowInternal(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal nonReentrant returns (uint, uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\\n }\\n\\n error = vTokenCollateral.accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\\n }\\n\\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\\n }\\n\\n /**\\n * @notice The liquidator liquidates the borrowers collateral.\\n * The collateral seized is transferred to the liquidator.\\n * @param borrower The borrower of this vToken to be liquidated\\n * @param liquidator The address repaying the borrow and seizing collateral\\n * @param vTokenCollateral The market in which to seize collateral from the borrower\\n * @param repayAmount The amount of the underlying borrowed asset to repay\\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\\n */\\n // solhint-disable-next-line code-complexity\\n function liquidateBorrowFresh(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) internal returns (uint, uint) {\\n /* Fail if liquidate not allowed */\\n uint allowed = comptroller.liquidateBorrowAllowed(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n repayAmount\\n );\\n if (allowed != 0) {\\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\\n }\\n\\n /* Verify market's block number equals current block number */\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Verify vTokenCollateral market's block number equals current block number */\\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\\n }\\n\\n /* Fail if repayAmount = 0 */\\n if (repayAmount == 0) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\\n }\\n\\n /* Fail if repayAmount = type(uint256).max */\\n if (repayAmount == type(uint256).max) {\\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\\n }\\n\\n /* Fail if repayBorrow fails */\\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\\n if (repayBorrowError != uint(Error.NO_ERROR)) {\\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We calculate the number of collateral tokens that will be seized */\\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\\n borrower,\\n address(this),\\n address(vTokenCollateral),\\n actualRepayAmount\\n );\\n\\n require(amountSeizeError == uint(Error.NO_ERROR), \\\"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\\\");\\n\\n /* Revert if borrower collateral token balance < seizeTokens */\\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \\\"LIQUIDATE_SEIZE_TOO_MUCH\\\");\\n\\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\\n uint seizeError;\\n if (address(vTokenCollateral) == address(this)) {\\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\\n } else {\\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\\n }\\n\\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\\n require(seizeError == uint(Error.NO_ERROR), \\\"token seizure failed\\\");\\n\\n /* We emit a LiquidateBorrow event */\\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.liquidateBorrowVerify(\\n address(this),\\n address(vTokenCollateral),\\n liquidator,\\n borrower,\\n actualRepayAmount,\\n seizeTokens\\n );\\n\\n return (uint(Error.NO_ERROR), actualRepayAmount);\\n }\\n\\n /**\\n * @notice Transfers collateral tokens (this market) to the liquidator.\\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\\n * @param liquidator The account receiving seized collateral\\n * @param borrower The account having collateral seized\\n * @param seizeTokens The number of vTokens to seize\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function seizeInternal(\\n address seizerToken,\\n address liquidator,\\n address borrower,\\n uint seizeTokens\\n ) internal returns (uint) {\\n /* Fail if seize not allowed */\\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n if (allowed != 0) {\\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\\n }\\n\\n /* Fail if borrower = liquidator */\\n if (borrower == liquidator) {\\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\\n }\\n\\n MathError mathErr;\\n uint borrowerTokensNew;\\n uint liquidatorTokensNew;\\n\\n /*\\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\\n */\\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\\n }\\n\\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\\n if (mathErr != MathError.NO_ERROR) {\\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /* We write the previously calculated values into storage */\\n accountTokens[borrower] = borrowerTokensNew;\\n accountTokens[liquidator] = liquidatorTokensNew;\\n\\n /* Emit a Transfer event */\\n emit Transfer(borrower, liquidator, seizeTokens);\\n\\n /* We call the defense and prime accrue interest hook */\\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\\n * @dev Governance function to set a new reserve factor\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\\n // Verify market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\\n }\\n\\n // Check newReserveFactor \\u2264 maxReserveFactor\\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\\n }\\n\\n uint oldReserveFactorMantissa = reserveFactorMantissa;\\n reserveFactorMantissa = newReserveFactorMantissa;\\n\\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\\n * @param addAmount Amount of addition to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\\n uint error = accrueInterest();\\n if (error != uint(Error.NO_ERROR)) {\\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\\n }\\n\\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\\n (error, ) = _addReservesFresh(addAmount);\\n return error;\\n }\\n\\n /**\\n * @notice Add reserves by transferring from caller\\n * @dev Requires fresh interest accrual\\n * @param addAmount Amount of addition to reserves\\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\\n */\\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\\n // totalReserves + actualAddAmount\\n uint totalReservesNew;\\n uint actualAddAmount;\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n /*\\n * We call doTransferIn for the caller and the addAmount\\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\\n * On success, the vToken holds an additional addAmount of cash.\\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n * it returns the amount actually transferred, in case of a fee.\\n */\\n\\n actualAddAmount = doTransferIn(msg.sender, addAmount);\\n\\n totalReservesNew = totalReserves + actualAddAmount;\\n\\n /* Revert on overflow */\\n require(totalReservesNew >= totalReserves, \\\"add reserves unexpected overflow\\\");\\n\\n // Store reserves[n+1] = reserves[n] + actualAddAmount\\n totalReserves = totalReservesNew;\\n\\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\\n\\n /* Return (NO_ERROR, actualAddAmount) */\\n return (uint(Error.NO_ERROR), actualAddAmount);\\n }\\n\\n /**\\n * @notice Reduces reserves by transferring to protocol share reserve contract\\n * @dev Requires fresh interest accrual\\n * @param reduceAmount Amount of reduction to reserves\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\\n if (reduceAmount == 0) {\\n return uint(Error.NO_ERROR);\\n }\\n\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\\n }\\n\\n // Fail gracefully if protocol has insufficient underlying cash\\n if (getCashPrior() < reduceAmount) {\\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\\n }\\n\\n // Check reduceAmount \\u2264 reserves[n] (totalReserves)\\n if (reduceAmount > totalReserves) {\\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\\n }\\n\\n /////////////////////////\\n // EFFECTS & INTERACTIONS\\n // (No safe failures beyond this point)\\n\\n // Store reserves[n+1] = reserves[n] - reduceAmount\\n totalReserves = totalReserves - reduceAmount;\\n\\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\\n doTransferOut(protocolShareReserve, reduceAmount);\\n\\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\\n address(comptroller),\\n underlying,\\n IProtocolShareReserve.IncomeType.SPREAD\\n );\\n\\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /**\\n * @notice updates the interest rate model (requires fresh interest accrual)\\n * @dev Governance function to update the interest rate model\\n * @param newInterestRateModel the new interest rate model to use\\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\\n */\\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\\n // We fail gracefully unless market's block number equals current block number\\n if (accrualBlockNumber != block.number) {\\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\\n }\\n\\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\\n require(newInterestRateModel.isInterestRateModel(), \\\"marker method returned false\\\");\\n\\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\\n\\n // Set the interest rate model to newInterestRateModel\\n interestRateModel = newInterestRateModel;\\n\\n return uint(Error.NO_ERROR);\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\\n * This may revert due to insufficient balance or insufficient allowance.\\n */\\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\\n\\n /**\\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\\n */\\n function doTransferOut(address payable to, uint amount) internal virtual;\\n\\n /**\\n * @notice Return the borrow balance of account based on stored data\\n * @param account The address whose balance should be calculated\\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\\n */\\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\\n /* Note: we do not assert that the market is up to date */\\n MathError mathErr;\\n uint principalTimesIndex;\\n uint result;\\n\\n /* Get borrowBalance and borrowIndex */\\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\\n\\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\\n */\\n if (borrowSnapshot.principal == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n /* Calculate new borrow balance using the interest index:\\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\\n */\\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, result);\\n }\\n\\n /**\\n * @notice Calculates the exchange rate from the underlying to the vToken\\n * @dev This function does not accrue interest before calculating the exchange rate\\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\\n */\\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\\n uint _totalSupply = totalSupply;\\n if (_totalSupply == 0) {\\n /*\\n * If there are no tokens minted:\\n * exchangeRate = initialExchangeRate\\n */\\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\\n } else {\\n /*\\n * Otherwise:\\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\\n */\\n uint totalCash = _getCashPriorWithFlashLoan();\\n uint cashPlusBorrowsMinusReserves;\\n Exp memory exchangeRate;\\n MathError mathErr;\\n\\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\\n if (mathErr != MathError.NO_ERROR) {\\n return (mathErr, 0);\\n }\\n\\n return (MathError.NO_ERROR, exchangeRate.mantissa);\\n }\\n }\\n\\n /**\\n * @notice Gets balance of this contract including active flash loans\\n * @return The quantity of underlying owned by this contract plus active flash loan amount\\n */\\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\\n return getCashPrior() + flashLoanAmount;\\n }\\n\\n function ensureAllowed(string memory functionSig) private view {\\n require(\\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\\n \\\"access denied\\\"\\n );\\n }\\n\\n function ensureAdmin(address caller_) private view {\\n require(caller_ == admin, \\\"Unauthorized\\\");\\n }\\n\\n function ensureNoMathError(MathError mErr) private pure {\\n require(mErr == MathError.NO_ERROR, \\\"math error\\\");\\n }\\n\\n function ensureNonZeroAddress(address address_) private pure {\\n require(address_ != address(0), \\\"zero address\\\");\\n }\\n\\n /*** Safe Token ***/\\n\\n /**\\n * @notice Gets balance of this contract in terms of the underlying\\n * @dev This excludes the value of the current message, if any\\n * @return The quantity of underlying owned by this contract\\n */\\n function getCashPrior() internal view virtual returns (uint);\\n}\\n\",\"keccak256\":\"0xa71b46dc3b3133980a99068c0e65a547317208f666196e28d38cc66a3808869b\",\"license\":\"BSD-3-Clause\"},\"contracts/Tokens/VTokens/VTokenInterfaces.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\nimport { ComptrollerInterface } from \\\"../../Comptroller/ComptrollerInterface.sol\\\";\\nimport { InterestRateModelV8 } from \\\"../../InterestRateModels/InterestRateModelV8.sol\\\";\\n\\ncontract VTokenStorageBase {\\n /**\\n * @notice Container for borrow balance information\\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\\n */\\n struct BorrowSnapshot {\\n uint principal;\\n uint interestIndex;\\n }\\n\\n /**\\n * @dev Guard variable for re-entrancy checks\\n */\\n bool internal _notEntered;\\n\\n /**\\n * @notice EIP-20 token name for this token\\n */\\n string public name;\\n\\n /**\\n * @notice EIP-20 token symbol for this token\\n */\\n string public symbol;\\n\\n /**\\n * @notice EIP-20 token decimals for this token\\n */\\n uint8 public decimals;\\n\\n /**\\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\\n */\\n\\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\\n\\n /**\\n * @notice Maximum fraction of interest that can be set aside for reserves\\n */\\n uint internal constant reserveFactorMaxMantissa = 1e18;\\n\\n /**\\n * @notice Administrator for this contract\\n */\\n address payable public admin;\\n\\n /**\\n * @notice Pending administrator for this contract\\n */\\n address payable public pendingAdmin;\\n\\n /**\\n * @notice Contract which oversees inter-vToken operations\\n */\\n ComptrollerInterface public comptroller;\\n\\n /**\\n * @notice Model which tells what the current interest rate should be\\n */\\n InterestRateModelV8 public interestRateModel;\\n\\n /**\\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\\n */\\n uint internal initialExchangeRateMantissa;\\n\\n /**\\n * @notice Fraction of interest currently set aside for reserves\\n */\\n uint public reserveFactorMantissa;\\n\\n /**\\n * @notice Block number that interest was last accrued at\\n */\\n uint public accrualBlockNumber;\\n\\n /**\\n * @notice Accumulator of the total earned interest rate since the opening of the market\\n */\\n uint public borrowIndex;\\n\\n /**\\n * @notice Total amount of outstanding borrows of the underlying in this market\\n */\\n uint public totalBorrows;\\n\\n /**\\n * @notice Total amount of reserves of the underlying held in this market\\n */\\n uint public totalReserves;\\n\\n /**\\n * @notice Total number of tokens in circulation\\n */\\n uint public totalSupply;\\n\\n /**\\n * @notice Official record of token balances for each account\\n */\\n mapping(address => uint) internal accountTokens;\\n\\n /**\\n * @notice Approved token transfer amounts on behalf of others\\n */\\n mapping(address => mapping(address => uint)) internal transferAllowances;\\n\\n /**\\n * @notice Mapping of account addresses to outstanding borrow balances\\n */\\n mapping(address => BorrowSnapshot) internal accountBorrows;\\n\\n /**\\n * @notice Underlying asset for this VToken\\n */\\n address public underlying;\\n\\n /**\\n * @notice Implementation address for this contract\\n */\\n address public implementation;\\n\\n /**\\n * @notice delta block after which reserves will be reduced\\n */\\n uint public reduceReservesBlockDelta;\\n\\n /**\\n * @notice last block number at which reserves were reduced\\n */\\n uint public reduceReservesBlockNumber;\\n\\n /**\\n * @notice address of protocol share reserve contract\\n */\\n address payable public protocolShareReserve;\\n\\n /**\\n * @notice address of accessControlManager\\n */\\n\\n address public accessControlManager;\\n}\\n\\ncontract VTokenStorage is VTokenStorageBase {\\n /**\\n * @notice flashLoan is enabled for this market or not\\n */\\n bool public isFlashLoanEnabled;\\n\\n /**\\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\\n */\\n uint256 public flashLoanFeeMantissa;\\n\\n /**\\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\\n */\\n uint256 public flashLoanProtocolShareMantissa;\\n\\n /**\\n * @notice Amount of flashLoan taken by the receiver\\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\\n */\\n uint256 public flashLoanAmount;\\n\\n /**\\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\\n */\\n uint256 public internalCash;\\n\\n /**\\n * @dev This empty reserved space is put in place to allow future versions to add new\\n * variables without shifting down storage in the inheritance chain.\\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\\n */\\n uint256[45] private __gap;\\n}\\n\\nabstract contract VTokenInterface is VTokenStorage {\\n /**\\n * @notice Indicator that this is a vToken contract (for inspection)\\n */\\n bool public constant isVToken = true;\\n\\n /*** Market Events ***/\\n\\n /**\\n * @notice Event emitted when interest is accrued\\n */\\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when tokens are minted\\n */\\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are minted behalf by payer to receiver\\n */\\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed\\n */\\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\\n\\n /**\\n * @notice Event emitted when tokens are redeemed and fee is transferred\\n */\\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\\n\\n /**\\n * @notice Event emitted when underlying is borrowed\\n */\\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is repaid\\n */\\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\\n\\n /**\\n * @notice Event emitted when a borrow is liquidated\\n */\\n event LiquidateBorrow(\\n address liquidator,\\n address borrower,\\n uint repayAmount,\\n address vTokenCollateral,\\n uint seizeTokens\\n );\\n\\n /*** Admin Events ***/\\n\\n /**\\n * @notice Event emitted when pendingAdmin is changed\\n */\\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\\n\\n /**\\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\\n */\\n event NewAdmin(address oldAdmin, address newAdmin);\\n\\n /**\\n * @notice Event emitted when comptroller is changed\\n */\\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\\n\\n /**\\n * @notice Event emitted when interestRateModel is changed\\n */\\n event NewMarketInterestRateModel(\\n InterestRateModelV8 oldInterestRateModel,\\n InterestRateModelV8 newInterestRateModel\\n );\\n\\n /**\\n * @notice Event emitted when the reserve factor is changed\\n */\\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\\n\\n /**\\n * @notice Event emitted when the reserves are added\\n */\\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\\n\\n /**\\n * @notice Event emitted when the reserves are reduced\\n */\\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\\n\\n /**\\n * @notice EIP20 Transfer event\\n */\\n event Transfer(address indexed from, address indexed to, uint amount);\\n\\n /**\\n * @notice EIP20 Approval event\\n */\\n event Approval(address indexed owner, address indexed spender, uint amount);\\n\\n /**\\n * @notice Event emitted when block delta for reduce reserves get updated\\n */\\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\\n\\n /**\\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\\n */\\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\\n\\n /**\\n * @notice Emitted when access control address is changed by admin\\n */\\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\\n\\n /**\\n * @notice Event emitted when flashLoanEnabled status is changed\\n */\\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\\n\\n /**\\n * @notice Event emitted when asset is transferred to receiver\\n */\\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\\n\\n /**\\n * @notice Event emitted when asset is transferred from sender and verified\\n */\\n event TransferInUnderlyingFlashLoan(\\n address indexed asset,\\n address indexed sender,\\n uint256 amount,\\n uint256 totalFee,\\n uint256 protocolFee\\n );\\n\\n /**\\n * @notice Event emitted when internalCash is synced with actual token balance\\n */\\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\\n\\n /**\\n * @notice Event emitted when excess tokens are swept by admin\\n */\\n event TokenSwept(address indexed recipient, uint256 amount);\\n\\n /**\\n * @notice Event emitted when flashLoan fee mantissa is updated\\n */\\n event FlashLoanFeeUpdated(\\n uint256 oldFlashLoanFeeMantissa,\\n uint256 newFlashLoanFeeMantissa,\\n uint256 oldFlashLoanProtocolShare,\\n uint256 newFlashLoanProtocolShare\\n );\\n\\n // @notice Thrown when comptroller is not valid\\n error InvalidComptroller();\\n\\n // @notice Thrown when there is already an active flashLoan\\n error FlashLoanAlreadyActive();\\n\\n /// @notice Thrown when flash loan fee exceeds maximum allowed\\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\\n\\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\\n\\n // @notice Thrown when the vToken does not have enough cash to lend\\n error InsufficientCash();\\n\\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\\n\\n /*** User Interface ***/\\n\\n function transfer(address dst, uint amount) external virtual returns (bool);\\n\\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\\n\\n function approve(address spender, uint amount) external virtual returns (bool);\\n\\n function balanceOfUnderlying(address owner) external virtual returns (uint);\\n\\n function totalBorrowsCurrent() external virtual returns (uint);\\n\\n function borrowBalanceCurrent(address account) external virtual returns (uint);\\n\\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _acceptAdmin() external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\\n\\n function balanceOf(address owner) external view virtual returns (uint);\\n\\n function allowance(address owner, address spender) external view virtual returns (uint);\\n\\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\\n\\n function borrowRatePerBlock() external view virtual returns (uint);\\n\\n function supplyRatePerBlock() external view virtual returns (uint);\\n\\n function getCash() external view virtual returns (uint);\\n\\n function exchangeRateCurrent() public virtual returns (uint);\\n\\n function accrueInterest() public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\\n\\n /*** Admin Function ***/\\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\\n\\n function borrowBalanceStored(address account) public view virtual returns (uint);\\n\\n function exchangeRateStored() public view virtual returns (uint);\\n}\\n\\ninterface VBep20Interface {\\n /*** User Interface ***/\\n\\n function mint(uint mintAmount) external returns (uint);\\n\\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\\n\\n function redeem(uint redeemTokens) external returns (uint);\\n\\n function redeemUnderlying(uint redeemAmount) external returns (uint);\\n\\n function borrow(uint borrowAmount) external returns (uint);\\n\\n function repayBorrow(uint repayAmount) external returns (uint);\\n\\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\\n\\n function liquidateBorrow(\\n address borrower,\\n uint repayAmount,\\n VTokenInterface vTokenCollateral\\n ) external returns (uint);\\n\\n /*** Admin Functions ***/\\n\\n function _addReserves(uint addAmount) external returns (uint);\\n}\\n\\ninterface VDelegatorInterface {\\n /**\\n * @notice Emitted when implementation is changed\\n */\\n event NewImplementation(address oldImplementation, address newImplementation);\\n\\n /**\\n * @notice Called by the admin to update the implementation of the delegator\\n * @param implementation_ The address of the new implementation for delegation\\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\\n */\\n function _setImplementation(\\n address implementation_,\\n bool allowResign,\\n bytes memory becomeImplementationData\\n ) external;\\n}\\n\\ninterface VDelegateInterface {\\n /**\\n * @notice Called by the delegator on a delegate to initialize it for duty\\n * @dev Should revert if any issues arise which make it unfit for delegation\\n * @param data The encoded bytes data for any initialization\\n */\\n function _becomeImplementation(bytes memory data) external;\\n\\n /**\\n * @notice Called by the delegator on a delegate to forfeit its responsibility\\n */\\n function _resignImplementation() external;\\n}\\n\",\"keccak256\":\"0xa892e7d531228f2bdc92ddf37be5c43fc29a7d952335397dede149d3ac182017\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/CarefulMath.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Careful Math\\n * @author Venus\\n * @notice Derived from OpenZeppelin's SafeMath library\\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\\n */\\ncontract CarefulMath {\\n /**\\n * @dev Possible error codes that we can return\\n */\\n enum MathError {\\n NO_ERROR,\\n DIVISION_BY_ZERO,\\n INTEGER_OVERFLOW,\\n INTEGER_UNDERFLOW\\n }\\n\\n /**\\n * @dev Multiplies two numbers, returns an error on overflow.\\n */\\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (a == 0) {\\n return (MathError.NO_ERROR, 0);\\n }\\n\\n uint c;\\n unchecked {\\n c = a * b;\\n }\\n\\n if (c / a != b) {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n } else {\\n return (MathError.NO_ERROR, c);\\n }\\n }\\n\\n /**\\n * @dev Integer division of two numbers, truncating the quotient.\\n */\\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b == 0) {\\n return (MathError.DIVISION_BY_ZERO, 0);\\n }\\n\\n return (MathError.NO_ERROR, a / b);\\n }\\n\\n /**\\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\\n */\\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n if (b <= a) {\\n unchecked {\\n return (MathError.NO_ERROR, a - b);\\n }\\n } else {\\n return (MathError.INTEGER_UNDERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev Adds two numbers, returns an error on overflow.\\n */\\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\\n uint c;\\n unchecked {\\n c = a + b;\\n }\\n\\n if (c >= a) {\\n return (MathError.NO_ERROR, c);\\n } else {\\n return (MathError.INTEGER_OVERFLOW, 0);\\n }\\n }\\n\\n /**\\n * @dev add a and b and then subtract c\\n */\\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\\n (MathError err0, uint sum) = addUInt(a, b);\\n\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, 0);\\n }\\n\\n return subUInt(sum, c);\\n }\\n}\\n\",\"keccak256\":\"0xb7ca049dc6f4a31c8994ad5fd2093b9f7f60c21495ff8386c7802ef13d9858a7\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ErrorReporter.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { WeightFunction } from \\\"../Comptroller/Diamond/interfaces/IFacetBase.sol\\\";\\n\\ncontract ComptrollerErrorReporter {\\n /// @notice Thrown when You are already in the selected pool.\\n error AlreadyInSelectedPool();\\n\\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\\n error IncompatibleBorrowedAssets();\\n\\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\\n\\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\\n error InvalidOperationForCorePool();\\n\\n /// @notice Thrown when input array lengths do not match\\n error ArrayLengthMismatch();\\n\\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\\n error MarketNotListedInCorePool();\\n\\n /// @notice Thrown when market is not set in the _poolMarkets mapping\\n error MarketConfigNotFound();\\n\\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\\n error BorrowNotAllowedInPool();\\n\\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\\n error PoolMarketNotFound(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when a given pool ID does not exist\\n error PoolDoesNotExist(uint96 poolId);\\n\\n /// @notice Thrown when the pool label is empty\\n error EmptyPoolLabel();\\n\\n /// @notice Thrown when a vToken is already listed in the specified pool\\n error MarketAlreadyListed(uint96 poolId, address vToken);\\n\\n /// @notice Thrown when an invalid weighting strategy is provided\\n error InvalidWeightingStrategy(WeightFunction strategy);\\n\\n // @notice Thrown when no assets are requested for flash loan\\n error NoAssetsRequested();\\n\\n // @notice Thrown when invalid flash loan parameters are provided\\n error InvalidFlashLoanParams();\\n\\n // @notice Thrown when flash loan is not enabled on the vToken\\n error FlashLoanNotEnabled();\\n\\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\\n error SenderNotAuthorizedForFlashLoan(address sender);\\n\\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\\n error NotAnApprovedDelegate();\\n\\n // @notice Thrown when executeOperation on the receiver contract fails\\n error ExecuteFlashLoanFailed();\\n\\n // @notice Thrown when the requested amount is zero\\n error InvalidAmount();\\n\\n // @notice Thrown when failing to create a debt position in mode 1\\n error FailedToCreateDebtPosition();\\n\\n /// @notice Thrown when attempting to interact with an inactive pool\\n error InactivePool(uint96 poolId);\\n\\n /// @notice Thrown when repayment amount is insufficient to cover the fee\\n error NotEnoughRepayment(uint256 repaid, uint256 required);\\n\\n /// @notice Thrown when the vToken market is not listed\\n error MarketNotListed(address vToken);\\n\\n /// @notice Thrown when flash loans are paused system-wide\\n error FlashLoanPausedSystemWide();\\n\\n /// @notice Thrown when too many assets are requested in a single flash loan\\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\\n\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n COMPTROLLER_MISMATCH,\\n INSUFFICIENT_SHORTFALL,\\n INSUFFICIENT_LIQUIDITY,\\n INVALID_CLOSE_FACTOR,\\n INVALID_COLLATERAL_FACTOR,\\n INVALID_LIQUIDATION_INCENTIVE,\\n MARKET_NOT_ENTERED, // no longer possible\\n MARKET_NOT_LISTED,\\n MARKET_ALREADY_LISTED,\\n MATH_ERROR,\\n NONZERO_BORROW_BALANCE,\\n PRICE_ERROR,\\n REJECTION,\\n SNAPSHOT_ERROR,\\n TOO_MANY_ASSETS,\\n TOO_MUCH_REPAY,\\n INSUFFICIENT_BALANCE_FOR_VAI,\\n MARKET_NOT_COLLATERAL,\\n INVALID_LIQUIDATION_THRESHOLD\\n }\\n\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n EXIT_MARKET_BALANCE_OWED,\\n EXIT_MARKET_REJECTION,\\n SET_CLOSE_FACTOR_OWNER_CHECK,\\n SET_CLOSE_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_NO_EXISTS,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\\n SET_IMPLEMENTATION_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_PRICE_ORACLE_OWNER_CHECK,\\n SUPPORT_MARKET_EXISTS,\\n SUPPORT_MARKET_OWNER_CHECK,\\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\\n SET_VAI_MINT_RATE_CHECK,\\n SET_VAICONTROLLER_OWNER_CHECK,\\n SET_MINTED_VAI_REJECTION,\\n SET_TREASURY_OWNER_CHECK,\\n UNLIST_MARKET_NOT_LISTED,\\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract TokenErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED,\\n BAD_INPUT,\\n COMPTROLLER_REJECTION,\\n COMPTROLLER_CALCULATION_ERROR,\\n INTEREST_RATE_MODEL_ERROR,\\n INVALID_ACCOUNT_PAIR,\\n INVALID_CLOSE_AMOUNT_REQUESTED,\\n INVALID_COLLATERAL_FACTOR,\\n MATH_ERROR,\\n MARKET_NOT_FRESH,\\n MARKET_NOT_LISTED,\\n TOKEN_INSUFFICIENT_ALLOWANCE,\\n TOKEN_INSUFFICIENT_BALANCE,\\n TOKEN_INSUFFICIENT_CASH,\\n TOKEN_TRANSFER_IN_FAILED,\\n TOKEN_TRANSFER_OUT_FAILED,\\n TOKEN_PRICE_ERROR\\n }\\n\\n /*\\n * Note: FailureInfo (but not Error) is kept in alphabetical order\\n * This is because FailureInfo grows significantly faster, and\\n * the order of Error has some meaning, while the order of FailureInfo\\n * is entirely arbitrary.\\n */\\n enum FailureInfo {\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n BORROW_ACCRUE_INTEREST_FAILED,\\n BORROW_CASH_NOT_AVAILABLE,\\n BORROW_FRESHNESS_CHECK,\\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n BORROW_MARKET_NOT_LISTED,\\n BORROW_COMPTROLLER_REJECTION,\\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n LIQUIDATE_COMPTROLLER_REJECTION,\\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n LIQUIDATE_FRESHNESS_CHECK,\\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_ACCRUE_INTEREST_FAILED,\\n MINT_COMPTROLLER_REJECTION,\\n MINT_EXCHANGE_CALCULATION_FAILED,\\n MINT_EXCHANGE_RATE_READ_FAILED,\\n MINT_FRESHNESS_CHECK,\\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n MINT_TRANSFER_IN_FAILED,\\n MINT_TRANSFER_IN_NOT_POSSIBLE,\\n REDEEM_ACCRUE_INTEREST_FAILED,\\n REDEEM_COMPTROLLER_REJECTION,\\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\\n REDEEM_EXCHANGE_RATE_READ_FAILED,\\n REDEEM_FRESHNESS_CHECK,\\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\\n REDUCE_RESERVES_ADMIN_CHECK,\\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\\n REDUCE_RESERVES_FRESH_CHECK,\\n REDUCE_RESERVES_VALIDATION,\\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_COMPTROLLER_REJECTION,\\n REPAY_BORROW_FRESHNESS_CHECK,\\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\\n SET_COLLATERAL_FACTOR_VALIDATION,\\n SET_COMPTROLLER_OWNER_CHECK,\\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\\n SET_MAX_ASSETS_OWNER_CHECK,\\n SET_ORACLE_MARKET_NOT_LISTED,\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\\n SET_RESERVE_FACTOR_ADMIN_CHECK,\\n SET_RESERVE_FACTOR_FRESH_CHECK,\\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\\n TRANSFER_COMPTROLLER_REJECTION,\\n TRANSFER_NOT_ALLOWED,\\n TRANSFER_NOT_ENOUGH,\\n TRANSFER_TOO_MUCH,\\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\\n ADD_RESERVES_FRESH_CHECK,\\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\\n REPAY_VAI_COMPTROLLER_REJECTION,\\n REPAY_VAI_FRESHNESS_CHECK,\\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\\ncontract VAIControllerErrorReporter {\\n enum Error {\\n NO_ERROR,\\n UNAUTHORIZED, // The sender is not authorized to perform this action.\\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\\n MATH_ERROR, // A math calculation error occurred.\\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\\n }\\n\\n enum FailureInfo {\\n SET_PENDING_ADMIN_OWNER_CHECK,\\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\\n SET_COMPTROLLER_OWNER_CHECK,\\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\\n VAI_MINT_REJECTION,\\n VAI_BURN_REJECTION,\\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\\n VAI_LIQUIDATE_FRESHNESS_CHECK,\\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\\n MINT_FEE_CALCULATION_FAILED,\\n SET_TREASURY_OWNER_CHECK\\n }\\n\\n /**\\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\\n **/\\n event Failure(uint error, uint info, uint detail);\\n\\n /**\\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\\n */\\n function fail(Error err, FailureInfo info) internal returns (uint) {\\n emit Failure(uint(err), uint(info), 0);\\n\\n return uint(err);\\n }\\n\\n /**\\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\\n */\\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\\n emit Failure(uint(err), uint(info), opaqueError);\\n\\n return uint(err);\\n }\\n}\\n\",\"keccak256\":\"0x9b498db9a2d5f5178b48e5724849f7561c1c0100c1faef4d6dbd741f599861f2\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/Exponential.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\nimport { CarefulMath } from \\\"./CarefulMath.sol\\\";\\nimport { ExponentialNoError } from \\\"./ExponentialNoError.sol\\\";\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Venus\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract Exponential is CarefulMath, ExponentialNoError {\\n /**\\n * @dev Creates an exponential from numerator and denominator values.\\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\\n * or if `denom` is zero.\\n */\\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\\n }\\n\\n /**\\n * @dev Adds two exponentials, returning a new exponential.\\n */\\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Subtracts two exponentials, returning a new exponential.\\n */\\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\\n\\n return (error, Exp({ mantissa: result }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, returning a new Exp.\\n */\\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(product));\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory product) = mulScalar(a, scalar);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return addUInt(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Divide an Exp by a scalar, returning a new Exp.\\n */\\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, returning a new Exp.\\n */\\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\\n /*\\n We are doing this as:\\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\\n\\n How it works:\\n Exp = a / b;\\n Scalar = s;\\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\\n */\\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n return getExp(numerator, divisor.mantissa);\\n }\\n\\n /**\\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\\n */\\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\\n if (err != MathError.NO_ERROR) {\\n return (err, 0);\\n }\\n\\n return (MathError.NO_ERROR, truncate(fraction));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials, returning a new exponential.\\n */\\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\\n if (err0 != MathError.NO_ERROR) {\\n return (err0, Exp({ mantissa: 0 }));\\n }\\n\\n // We add half the scale before dividing so that we get rounding instead of truncation.\\n // See \\\"Listing 6\\\" and text above it at https://accu.org/index.php/journals/1717\\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\\n if (err1 != MathError.NO_ERROR) {\\n return (err1, Exp({ mantissa: 0 }));\\n }\\n\\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\\n assert(err2 == MathError.NO_ERROR);\\n\\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\\n }\\n\\n /**\\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\\n */\\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\\n }\\n\\n /**\\n * @dev Multiplies three exponentials, returning a new exponential.\\n */\\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\\n (MathError err, Exp memory ab) = mulExp(a, b);\\n if (err != MathError.NO_ERROR) {\\n return (err, ab);\\n }\\n return mulExp(ab, c);\\n }\\n\\n /**\\n * @dev Divides two exponentials, returning a new exponential.\\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\\n */\\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\\n return getExp(a.mantissa, b.mantissa);\\n }\\n}\\n\",\"keccak256\":\"0x6b9b293a09a3ec69ac16f58dce449a553b44121eb9aad666a777d8f6f4ae83f0\",\"license\":\"BSD-3-Clause\"},\"contracts/Utils/ExponentialNoError.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\npragma solidity 0.8.25;\\n\\n/**\\n * @title Exponential module for storing fixed-precision decimals\\n * @author Compound\\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\\n * `Exp({mantissa: 5100000000000000000})`.\\n */\\ncontract ExponentialNoError {\\n uint internal constant expScale = 1e18;\\n uint internal constant doubleScale = 1e36;\\n uint internal constant halfExpScale = expScale / 2;\\n uint internal constant mantissaOne = expScale;\\n\\n struct Exp {\\n uint mantissa;\\n }\\n\\n struct Double {\\n uint mantissa;\\n }\\n\\n /**\\n * @dev Truncates the given exp to a whole number value.\\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\\n */\\n function truncate(Exp memory exp) internal pure returns (uint) {\\n // Note: We are not using careful math here as we're performing a division that cannot fail\\n return exp.mantissa / expScale;\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\\n */\\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return truncate(product);\\n }\\n\\n /**\\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\\n */\\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\\n Exp memory product = mul_(a, scalar);\\n return add_(truncate(product), addend);\\n }\\n\\n /**\\n * @dev Checks if first Exp is less than second Exp.\\n */\\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa < right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp <= right Exp.\\n */\\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa <= right.mantissa;\\n }\\n\\n /**\\n * @dev Checks if left Exp > right Exp.\\n */\\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\\n return left.mantissa > right.mantissa;\\n }\\n\\n /**\\n * @dev returns true if Exp is exactly zero\\n */\\n function isZeroExp(Exp memory value) internal pure returns (bool) {\\n return value.mantissa == 0;\\n }\\n\\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\\n require(n < 2 ** 224, errorMessage);\\n return uint224(n);\\n }\\n\\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\\n require(n < 2 ** 32, errorMessage);\\n return uint32(n);\\n }\\n\\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\\n }\\n\\n function add_(uint a, uint b) internal pure returns (uint) {\\n return add_(a, b, \\\"addition overflow\\\");\\n }\\n\\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n uint c = a + b;\\n require(c >= a, errorMessage);\\n return c;\\n }\\n\\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\\n }\\n\\n function sub_(uint a, uint b) internal pure returns (uint) {\\n return sub_(a, b, \\\"subtraction underflow\\\");\\n }\\n\\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n\\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\\n }\\n\\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / expScale;\\n }\\n\\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\\n }\\n\\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: mul_(a.mantissa, b) });\\n }\\n\\n function mul_(uint a, Double memory b) internal pure returns (uint) {\\n return mul_(a, b.mantissa) / doubleScale;\\n }\\n\\n function mul_(uint a, uint b) internal pure returns (uint) {\\n return mul_(a, b, \\\"multiplication overflow\\\");\\n }\\n\\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n if (a == 0 || b == 0) {\\n return 0;\\n }\\n uint c = a * b;\\n require(c / a == b, errorMessage);\\n return c;\\n }\\n\\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\\n }\\n\\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\\n return Exp({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Exp memory b) internal pure returns (uint) {\\n return div_(mul_(a, expScale), b.mantissa);\\n }\\n\\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\\n }\\n\\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(a.mantissa, b) });\\n }\\n\\n function div_(uint a, Double memory b) internal pure returns (uint) {\\n return div_(mul_(a, doubleScale), b.mantissa);\\n }\\n\\n function div_(uint a, uint b) internal pure returns (uint) {\\n return div_(a, b, \\\"divide by zero\\\");\\n }\\n\\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n\\n function fraction(uint a, uint b) internal pure returns (Double memory) {\\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\\n }\\n}\\n\",\"keccak256\":\"0xce75802a56763fb96b2046b374127f080a425cfe3634670767ec040ccb6ea7e0\",\"license\":\"BSD-3-Clause\"},\"contracts/external/IProtocolShareReserve.sol\":{\"content\":\"// SPDX-License-Identifier: BSD-3-Clause\\n\\npragma solidity 0.8.25;\\n\\ninterface IProtocolShareReserve {\\n enum IncomeType {\\n SPREAD,\\n LIQUIDATION,\\n ERC4626_WRAPPER_REWARDS,\\n FLASHLOAN\\n }\\n\\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\\n}\\n\",\"keccak256\":\"0x029861e068e9c4d802650eaf6dd8cfed0980d2ce9a45e6fcc1e1e628ecc1f523\",\"license\":\"BSD-3-Clause\"}},\"version\":1}", + "bytecode": "0x6080604052348015600e575f80fd5b506143058061001c5f395ff3fe608060405234801561000f575f80fd5b506004361061028b575f3560e01c8063691e45ac11610161578063b49b1005116100ca578063d24febad11610084578063d24febad146105a1578063e44e6168146105b4578063ee1fa41e146105fa578063f20fd8f41461060e578063f7260d3e1461062d578063f851a44014610640575f80fd5b8063b49b100514610547578063b9ee87261461054f578063c32094c714610557578063c5f956af1461056a578063c7ee005e1461057d578063cbeb2b2814610590575f80fd5b806378c2f9221161011b57806378c2f922146104de5780637a37c5d0146104f15780638129fc1c14610510578063b06bb42614610518578063b2b481bc1461052b578063b2eafc3914610534575f80fd5b8063691e45ac1461046f5780636fe74a211461049d578063718da7ee146104b0578063741de148146104c357806375c3de43146104cd57806376c71ca1146104d5575f80fd5b80633785d1d6116102035780635ce73240116101bd5780635ce732401461040c5780635fe3b5671461041557806360c954ef1461042857806361b3311c146104455780636509795414610458578063657bdf9414610467575f80fd5b80633785d1d6146103a45780633b5a0a64146103b75780633b72fbef146103ca5780634070a0c9146103d35780634576b5db146103e65780634712ee7d146103f9575f80fd5b80631d08837b116102545780631d08837b146103265780631d504dc6146103395780631f040ff51461034c578063234f89771461035f57806324650602146103725780632678224714610391575f80fd5b80623b58841461028f57806304ef9d58146102bf57806311b3d5e7146102d657806313007d55146102fe57806319129e5a14610311575b5f80fd5b6002546102a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102c8600a5481565b6040519081526020016102b6565b6102e96102e4366004613ccd565b610652565b604080519283526020830191909152016102b6565b6014546102a2906001600160a01b031681565b61032461031f366004613d0c565b61074d565b005b610324610334366004613d27565b6107e1565b610324610347366004613d0c565b610854565b6102e961035a366004613d3e565b6109cd565b6102c861036d366004613d0c565b610a2a565b6102c8610380366004613d0c565b60076020525f908152604090205481565b6001546102a2906001600160a01b031681565b6102e96103b2366004613d0c565b610a5f565b6103246103c5366004613d27565b6113a1565b6102c8600c5481565b6103246103e1366004613d27565b611415565b6102c86103f4366004613d0c565b611487565b6102c8610407366004613d27565b61150b565b6102c8600d5481565b6004546102a2906001600160a01b031681565b6006546104359060ff1681565b60405190151581526020016102b6565b610324610453366004613d0c565b611b18565b6102c8670de0b6b3a764000081565b6102c8611baa565b61048261047d366004613d3e565b611c83565b604080519384526020840192909252908201526060016102b6565b6102e96104ab366004613d27565b612120565b6103246104be366004613d0c565b612172565b63042d56006102c8565b6102c86121fe565b6102c860135481565b6102c86104ec366004613d0c565b61224f565b6104f85f81565b6040516001600160601b0390911681526020016102b6565b610324612436565b6003546102a2906001600160a01b031681565b6102c8600f5481565b6008546102a2906001600160a01b031681565b6103246124c9565b6102c86125c3565b610324610565366004613d0c565b612814565b6009546102a2906001600160a01b031681565b6015546102a2906001600160a01b031681565b6016546001600160a01b03166102a2565b6102c86105af366004613d68565b6128a6565b6005546105d6906001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016102b6565b60155461043590600160a01b900460ff1681565b6102c861061c366004613d0c565b60126020525f908152604090205481565b600e546102a2906001600160a01b031681565b5f546102a2906001600160a01b031681565b600b545f90819060ff166106815760405162461bcd60e51b815260040161067890613da6565b60405180910390fd5b600b805460ff19169055610693612a3b565b5f836001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303815f875af11580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190613dca565b905080156107245761071981600681111561071257610712613de1565b6008612ae8565b5f9250925050610736565b61073033878787612b5f565b92509250505b600b805460ff191660011790559094909350915050565b5f546001600160a01b031633146107765760405162461bcd60e51b815260040161067890613df5565b61077f81613088565b601480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd491015b60405180910390a15050565b6108166040518060400160405280601481526020017373657442617365526174652875696e743235362960601b8152506130d6565b600c80549082905560408051828152602081018490527fc84c32795e68685ec107b0e94ae126ef464095f342c7e2e0fec06a23d2e8677e91016107d5565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b49190613e1d565b6001600160a01b0316336001600160a01b0316146109245760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610678565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610961573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109859190613dca565b156109ca5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610678565b50565b600b545f90819060ff166109f35760405162461bcd60e51b815260040161067890613da6565b600b805460ff19169055610a0684613088565b610a108484613183565b91509150600b805460ff1916600117905590939092509050565b6001600160a01b0381165f90815260116020526040812054808203610a595750670de0b6b3a764000092915050565b92915050565b6015545f908190600160a01b900460ff168015610ae55750601554604051630e3da90d60e21b81526001600160a01b038581166004830152909116906338f6a43490602401602060405180830381865afa158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae39190613e4c565b155b15610af5576002935f9350915050565b60048054604051632aff3bff60e21b81526001600160a01b03868116938201939093525f929091169063abfceffc906024015f60405180830381865afa158015610b41573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b689190810190613e84565b90505f60045f9054906101000a90046001600160a01b03166001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bdf9190613e1d565b9050610be9613c07565b82515f9081905b808210156110e557858281518110610c0a57610c0a613f44565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038b811660048301529091169063c37f68e290602401608060405180830381865afa158015610c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613f58565b60e088015260c087015260a086015280855215610ca75760035b995f9950975050505050505050565b60405180602001604052808560e00151815250846101400181905250846001600160a01b03166388142b6b878481518110610ce457610ce4613f44565b60200260200101516040518263ffffffff1660e01b8152600401610d1791906001600160a01b0391909116815260200190565b6040805180830381865afa158015610d31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d559190613f8b565b61012086015261010085018190521580610d725750610120840151155b15610d7e576004610c98565b604080516020808201835261010087015182526101608701918252825190810190925261012086015182526101808601919091526101408501519051610dc491906131d1565b85602001866101a001829052826003811115610de257610de2613de1565b6003811115610df357610df3613de1565b9052505f905084602001516003811115610e0f57610e0f613de1565b14610e1b576005610c98565b610e2e846101a001518560a001516132de565b6060860181905260208601826003811115610e4b57610e4b613de1565b6003811115610e5c57610e5c613de1565b9052505f905084602001516003811115610e7857610e78613de1565b14610e84576005610c98565b60045486515f916001600160a01b031690638e8f294b90899086908110610ead57610ead613f44565b60200260200101516040518263ffffffff1660e01b8152600401610ee091906001600160a01b0391909116815260200190565b60e060405180830381865afa158015610efb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f1f9190613fc3565b5050505050915050610f3585606001518261332b565b6060870181905260208701826003811115610f5257610f52613de1565b6003811115610f6357610f63613de1565b9052505f905085602001516003811115610f7f57610f7f613de1565b14610f975760055b9a5f9a5098505050505050505050565b610fad8560600151670de0b6b3a7640000613368565b6060870181905260208701826003811115610fca57610fca613de1565b6003811115610fdb57610fdb613de1565b9052505f905085602001516003811115610ff757610ff7613de1565b14611003576005610f87565b61101585604001518660600151613387565b604087018190526020870182600381111561103257611032613de1565b600381111561104357611043613de1565b9052505f90508560200151600381111561105f5761105f613de1565b1461106b576005610f87565b6110838561018001518660c0015187608001516133aa565b60808701819052602087018260038111156110a0576110a0613de1565b60038111156110b1576110b1613de1565b9052505f9050856020015160038111156110cd576110cd613de1565b146110d9576005610f87565b50600190910190610bf0565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611132573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111569190613dca565b90505f811561116b576111688b61224f565b90505b611179866080015182613387565b608088018190526020880182600381111561119657611196613de1565b60038111156111a7576111a7613de1565b9052505f9050866020015160038111156111c3576111c3613de1565b146111dc5760055b9b5f9b509950505050505050505050565b61125d866040015160045f9054906101000a90046001600160a01b03166001600160a01b031663bec04f726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611234573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112589190613dca565b61332b565b8760200181975082600381111561127657611276613de1565b600381111561128757611287613de1565b9052505f9050866020015160038111156112a3576112a3613de1565b146112c05760405162461bcd60e51b81526004016106789061402f565b6112cc85612710613368565b876020018197508260038111156112e5576112e5613de1565b60038111156112f6576112f6613de1565b9052505f90508660200151600381111561131257611312613de1565b1461132f5760405162461bcd60e51b81526004016106789061402f565b61133d858760800151613401565b8760200181975082600381111561135657611356613de1565b600381111561136757611367613de1565b9052505f90508660200151600381111561138357611383613de1565b1461138f5760026111cb565b5f9b949a509398505050505050505050565b6113d760405180604001604052806015815260200174736574466c6f6174526174652875696e743235362960581b8152506130d6565b600d80549082905560408051828152602081018490527f546fb35dbbd92233aecc22b5a11a6791e5db7ec14f62e49cbac2a10c0437f56191016107d5565b611449604051806040016040528060138152602001727365744d696e744361702875696e743235362960681b8152506130d6565b601380549082905560408051828152602081018490527f43862b3eea2df8fce70329f3f84cbcad220f47a73be46c5e00df25165a6e169591016107d5565b5f80546001600160a01b031633146114a557610a5960016002612ae8565b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d910160405180910390a15f5b9392505050565b600b545f9060ff1661152f5760405162461bcd60e51b815260040161067890613da6565b600b805460ff191690556004546001600160a01b031661155057505f611b06565b60048054604051637376909960e01b815233928101929092525f916001600160a01b0390911690637376909990602401602060405180830381865afa15801561159b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115bf9190614071565b6001600160601b0316146116245760405162461bcd60e51b815260206004820152602660248201527f564149206d696e74206f6e6c7920616c6c6f77656420696e2074686520636f726044820152651948141bdbdb60d21b6064820152608401610678565b61162d82613421565b611635612a3b565b61163d6124c9565b601654604080516318160ddd60e01b815290515f9233926001600160a01b0390911691849183916318160ddd916004808201926020929091908290030181865afa15801561168d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b19190613dca565b90505f6116be8288613467565b90506013548111156117055760405162461bcd60e51b815260206004820152601060248201526f1b5a5b9d0818d85c081c995858da195960821b6044820152606401610678565b61170e8461349c565b5f61171885610a5f565b909650905085156117755760405162461bcd60e51b815260206004820152602160248201527f636f756c64206e6f7420636f6d70757465206d696e7461626c6520616d6f756e6044820152601d60fa1b6064820152608401610678565b808811156117c55760405162461bcd60e51b815260206004820152601960248201527f6d696e74696e67206d6f7265207468616e20616c6c6f776564000000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b03888116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611812573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118369190613dca565b90508015611896575f6118488761224f565b90505f6118558284613628565b6001600160a01b0389165f9081526012602052604090205490915061187a9082613467565b6001600160a01b0389165f908152601260205260409020555090505b5f6118a1828b613467565b6004805460405163fd51a3ad60e01b81526001600160a01b038b81169382019390935260248101849052929350169063fd51a3ad906044016020604051808303815f875af11580156118f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119199190613dca565b975087156119615760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f600a545f14611a41575f61198961197b8d600a54613661565b670de0b6b3a76400006136a2565b90506119958c82613628565b6009546040516340c10f1960e01b81526001600160a01b039182166004820152602481018490529193508916906340c10f19906044015f604051808303815f87803b1580156119e2575f80fd5b505af11580156119f4573d5f803e3d5ffd5b5050604080516001600160a01b038d168152602081018590527fb0715a6d41a37c1b0672c22c09a31a0642c1fb3f9efa2d5fd5c6d2d891ee78c6935001905060405180910390a150611a44565b50895b6040516340c10f1960e01b81526001600160a01b038981166004830152602482018390528816906340c10f19906044015f604051808303815f87803b158015611a8b575f80fd5b505af1158015611a9d573d5f803e3d5ffd5b5050600f546001600160a01b038b165f818152601160209081526040918290209390935580519182529181018590527e2e68ab1600fc5e7290e2ceaa79e2f86b4dbaca84a48421e167e0b40409218a935001905060405180910390a15f99505050505050505050505b600b805460ff19166001179055919050565b5f546001600160a01b03163314611b415760405162461bcd60e51b815260040161067890613df5565b601654604080516001600160a01b03928316815291831660208301527fe45150fb0a88e2274ecbca05ddde9925dd64b6e126ae0fa23ee2d42e668a49d3910160405180910390a1601680546001600160a01b0319166001600160a01b0392909216919091179055565b5f611be96040518060400160405280601b81526020017f746f67676c654f6e6c795072696d65486f6c6465724d696e74282900000000008152506130d6565b601554600160a01b900460ff16158015611c0c57506015546001600160a01b0316155b15611c175750600290565b60155460408051600160a01b90920460ff16158015835260208301527f8efa7b6021d602e0cdef814b7435609ee40deb2a0352ca676d10045750516a5f910160405180910390a16015805460ff60a01b198116600160a01b9182900460ff16159091021790555f905090565b5f805f805f611c918761224f565b600480546040516315e3f14f60e11b81526001600160a01b038b8116938201939093529293505f92611d0e9285921690632bc7e29e90602401602060405180830381865afa158015611ce5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d099190613dca565b613401565b90935090505f836003811115611d2657611d26613de1565b14611d435760405162461bcd60e51b81526004016106789061408a565b6001600160a01b0388165f90815260126020526040902054611d659082613387565b90935090505f836003811115611d7d57611d7d613de1565b14611d9a5760405162461bcd60e51b81526004016106789061408a565b6001600160a01b0388165f908152601260205260408120548290848a10611dff57611dc58585613401565b90965092505f866003811115611ddd57611ddd613de1565b14611dfa5760405162461bcd60e51b81526004016106789061408a565b61210f565b5f611e128b670de0b6b3a764000061332b565b90975090505f876003811115611e2a57611e2a613de1565b14611e775760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b611e818187613368565b90975090505f876003811115611e9957611e99613de1565b14611ee65760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b5f611ef18787613401565b90985090505f886003811115611f0957611f09613de1565b14611f625760405162461bcd60e51b8152602060048201526024808201527f5641495f4d494e5445445f414d4f554e545f43414c43554c4154494f4e5f46416044820152631253115160e21b6064820152608401610678565b611f6c818361332b565b90985094505f886003811115611f8457611f84613de1565b14611fa15760405162461bcd60e51b81526004016106789061408a565b611fb385670de0b6b3a7640000613368565b90985094505f886003811115611fcb57611fcb613de1565b14611fe85760405162461bcd60e51b81526004016106789061408a565b611ff2868361332b565b90985093505f88600381111561200a5761200a613de1565b146120275760405162461bcd60e51b8152600401610678906140cc565b61203984670de0b6b3a7640000613368565b90985093505f88600381111561205157612051613de1565b1461206e5760405162461bcd60e51b8152600401610678906140cc565b6001600160a01b038d165f90815260126020526040902054612090908361332b565b90985092505f8860038111156120a8576120a8613de1565b146120c55760405162461bcd60e51b81526004016106789061411a565b6120d783670de0b6b3a7640000613368565b90985092505f8860038111156120ef576120ef613de1565b1461210c5760405162461bcd60e51b81526004016106789061411a565b50505b919750955093505050509250925092565b600b545f90819060ff166121465760405162461bcd60e51b815260040161067890613da6565b600b805460ff1916905561215a3384613183565b91509150600b805460ff191660011790559092909150565b5f546001600160a01b0316331461219b5760405162461bcd60e51b815260040161067890613df5565b6121a481613088565b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f4df62dd7d9cc4f480a167c19c616ae5d5bb40db6d0c2bc66dba57068225f00d891016107d5565b5f806122086125c3565b90505f8061221a8363042d5600613368565b90925090505f82600381111561223257612232613de1565b146115045760405162461bcd60e51b81526004016106789061415e565b600480546040516315e3f14f60e11b81526001600160a01b03848116938201939093525f9283928392839290911690632bc7e29e90602401602060405180830381865afa1580156122a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122c69190613dca565b6001600160a01b0386165f90815260126020526040812054919250806122ec8484613401565b90965091505f86600381111561230457612304613de1565b146123215760405162461bcd60e51b81526004016106789061419f565b612330600f54611d098a610a2a565b90965094505f86600381111561234857612348613de1565b146123655760405162461bcd60e51b81526004016106789061419f565b61236f858361332b565b90965090505f86600381111561238757612387613de1565b146123a45760405162461bcd60e51b81526004016106789061419f565b6123b681670de0b6b3a7640000613368565b90965090505f8660038111156123ce576123ce613de1565b146123eb5760405162461bcd60e51b81526004016106789061419f565b6123f58482613387565b90965093505f86600381111561240d5761240d613de1565b1461242a5760405162461bcd60e51b81526004016106789061419f565b50919695505050505050565b5f546001600160a01b0316331461245f5760405162461bcd60e51b815260040161067890613df5565b600f54156124a55760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610678565b670de0b6b3a7640000600f55436010555f19601355600b805460ff19166001179055565b5f806124e36124d66121fe565b60105461125890436141fc565b90925090505f8260038111156124fb576124fb613de1565b146125485760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b61255481600f54613387565b90925090505f82600381111561256c5761256c613de1565b146125b95760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b600f555043601055565b60048054604080516307dc0d1d60e41b815290515f9384936001600160a01b031692637dc0d1d092818301926020928290030181865afa158015612609573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061262d9190613e1d565b90505f80600c54111561280c57600d5415612802575f826001600160a01b031663fc57d4df6126646016546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156126a6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126ca9190613dca565b905080670de0b6b3a764000011156127f7575f806126f0670de0b6b3a764000084613401565b90945091505f84600381111561270857612708613de1565b146127255760405162461bcd60e51b81526004016106789061415e565b61273182600d5461332b565b90945091505f84600381111561274957612749613de1565b146127665760405162461bcd60e51b81526004016106789061415e565b61277882670de0b6b3a7640000613368565b90945091505f84600381111561279057612790613de1565b146127ad5760405162461bcd60e51b81526004016106789061415e565b6127b982600c54613387565b90945090505f8460038111156127d1576127d1613de1565b146127ee5760405162461bcd60e51b81526004016106789061415e565b95945050505050565b600c54935050505090565b600c549250505090565b5f9250505090565b5f546001600160a01b0316331461283d5760405162461bcd60e51b815260040161067890613df5565b601554604080516001600160a01b03928316815291831660208301527ffb26401242c61b503dd09c29da64a5d4f451549f574b882a40bcdc64ee68b83c910160405180910390a1601580546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b03163314806128c957506008546001600160a01b031633145b6128e0576128d960016017612ae8565b9050611504565b670de0b6b3a764000082106129375760405162461bcd60e51b815260206004820152601d60248201527f74726561737572792070657263656e7420636170206f766572666c6f770000006044820152606401610678565b6008805460098054600a80546001600160a01b03198086166001600160a01b038c81169182179098559084168a8816179094559087905560408051948616808652602086019490945292949091169290917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e8910160405180910390a1604080516001600160a01b038085168252881660208201527f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac910160405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a1505f9695505050505050565b600480546040805163084bf5ab60e31b815290516001600160a01b039092169263425fad589282820192602092908290030181865afa158015612a80573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa49190613e4c565b15612ae65760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610678565b565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836006811115612b1c57612b1c613de1565b836017811115612b2e57612b2e613de1565b6040805192835260208301919091525f9082015260600160405180910390a182600681111561150457611504613de1565b6004545f9081906001600160a01b03161561307f57612b7c6124c9565b60048054604051632fe3f38f60e11b815230928101929092526001600160a01b03858116602484015288811660448401528781166064840152608483018790525f92911690635fc7e71e9060a4016020604051808303815f875af1158015612be6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c0a9190613dca565b90508015612c2a57612c1f6002600a836136d4565b5f925092505061307f565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c67573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c8b9190613dca565b14612c9c57612c1f60026009612ae8565b866001600160a01b0316866001600160a01b031603612cc157612c1f6002600f612ae8565b845f03612cd457612c1f6002600d612ae8565b5f198503612ce857612c1f6002600c612ae8565b5f80612cf5898989613753565b90925090508115612d2957612d1c826006811115612d1557612d15613de1565b6010612ae8565b5f9450945050505061307f565b6004805460405163a78dc77560e01b81526001600160a01b0389811693820193909352602481018490525f928392169063a78dc775906044016040805180830381865afa158015612d7c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da09190613f8b565b90925090508115612e195760405162461bcd60e51b815260206004820152603760248201527f5641495f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c60448201527f4154455f414d4f554e545f5345495a455f4641494c45440000000000000000006064820152608401610678565b6040516370a0823160e01b81526001600160a01b038b811660048301528291908a16906370a0823190602401602060405180830381865afa158015612e60573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e849190613dca565b1015612ed25760405162461bcd60e51b815260206004820152601c60248201527f5641495f4c49515549444154455f5345495a455f544f4f5f4d554348000000006044820152606401610678565b60405163b2a02ff160e01b81526001600160a01b038c811660048301528b81166024830152604482018390525f91908a169063b2a02ff1906064016020604051808303815f875af1158015612f29573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613dca565b90508015612f945760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610678565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f42d401f96718a0c42e5cea8108973f0022677b7e2e5f4ee19851b2de7a0394e79181900360a00190a1600480546040516347ef3b3b60e01b815230928101929092526001600160a01b038b811660248401528e811660448401528d811660648401526084830187905260a4830185905216906347ef3b3b9060c4015f604051808303815f87803b158015613056575f80fd5b505af1158015613068573d5f803e3d5ffd5b505f9250613074915050565b975092955050505050505b94509492505050565b6001600160a01b0381166109ca5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610678565b6014546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90613108903390859060040161423d565b602060405180830381865afa158015613123573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131479190613e4c565b6109ca5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610678565b6004545f9081906001600160a01b03166131a157505f9050806131ca565b6131aa83613421565b6131b2612a3b565b6131ba6124c9565b6131c5338585613753565b915091505b9250929050565b5f6131e760405180602001604052805f81525090565b5f806131f9865f0151865f015161332b565b90925090505f82600381111561321157613211613de1565b1461322f575060408051602081019091525f815290925090506131ca565b5f8061324d6132476002670de0b6b3a7640000614260565b84613387565b90925090505f82600381111561326557613265613de1565b14613287578160405180602001604052805f81525095509550505050506131ca565b5f8061329b83670de0b6b3a7640000613368565b90925090505f8260038111156132b3576132b3613de1565b146132c0576132c061427f565b60408051602081019091529081525f9a909950975050505050505050565b5f805f806132ec8686613a99565b90925090505f82600381111561330457613304613de1565b14613314575091505f90506131ca565b5f61331e82613b0e565b9350935050509250929050565b5f80835f0361333e57505f9050806131ca565b8383028361334c8683614260565b1461335e5760025f92509250506131ca565b5f925090506131ca565b5f80825f0361337c5750600190505f6131ca565b5f6131c58486614260565b5f8083830184811061339d575f925090506131ca565b60025f92509250506131ca565b5f805f806133b88787613a99565b90925090505f8260038111156133d0576133d0613de1565b146133e0575091505f90506133f9565b6133f26133ec82613b0e565b86613387565b9350935050505b935093915050565b5f8083831161341657505f90508183036131ca565b50600390505f6131ca565b5f81116109ca5760405162461bcd60e51b8152602060048201526014602482015273616d6f756e742063616e2774206265207a65726f60601b6044820152606401610678565b5f6115048383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250613b25565b5f60045f9054906101000a90046001600160a01b03166001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135119190613e1d565b60048054604051632aff3bff60e21b81526001600160a01b03868116938201939093529293505f9291169063abfceffc906024015f60405180830381865afa15801561355f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526135869190810190613e84565b80519091505f5b8181101561362157836001600160a01b031663a9c3cab18483815181106135b6576135b6613f44565b60200260200101516040518263ffffffff1660e01b81526004016135e991906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015613600575f80fd5b505af1158015613612573d5f803e3d5ffd5b5050505080600101905061358d565b5050505050565b5f6115048383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250613b5e565b5f61150483836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250613b8c565b5f61150483836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613bdc565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084600681111561370857613708613de1565b84601781111561371a5761371a613de1565b604080519283526020830191909152810184905260600160405180910390a183600681111561374b5761374b613de1565b949350505050565b5f805f805f6137628787611c83565b601654604051632770a7eb60e21b81526001600160a01b038d811660048301526024820186905294975092955090935091909116908190639dc29fac906044015f604051808303815f87803b1580156137b9575f80fd5b505af11580156137cb573d5f803e3d5ffd5b5050600e546040516323b872dd60e01b81526001600160a01b038d811660048301529182166024820152604481018790525f935090841691506323b872dd906064016020604051808303815f875af1158015613829573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061384d9190613e4c565b90506001811515146138a15760405162461bcd60e51b815260206004820152601a60248201527f6661696c656420746f207472616e7366657220564149206665650000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa1580156138ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139129190613dca565b90505f6139286139228389613628565b86613628565b6001600160a01b038c165f9081526012602052604090205490915061394d9086613628565b6001600160a01b03808d165f818152601260205260408082209490945560048054945163fd51a3ad60e01b81529081019290925260248201859052929091169063fd51a3ad906044016020604051808303815f875af11580156139b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139d69190613dca565b90508015613a1e5760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f613a298989613467565b90507f1db858e6f7e1a0d5e92c10c6507d42b3dabfe0a4867fe90c5a14d9963662ef7e8e8e83604051613a7d939291906001600160a01b039384168152919092166020820152604081019190915260600190565b60405180910390a15f9e909d509b505050505050505050505050565b5f613aaf60405180602001604052805f81525090565b5f80613abe865f01518661332b565b90925090505f826003811115613ad657613ad6613de1565b14613af4575060408051602081019091525f815290925090506131ca565b60408051602081019091529081525f969095509350505050565b80515f90610a5990670de0b6b3a764000090614260565b5f80613b318486614293565b90508285821015613b555760405162461bcd60e51b815260040161067891906142a6565b50949350505050565b5f8184841115613b815760405162461bcd60e51b815260040161067891906142a6565b5061374b83856141fc565b5f831580613b98575082155b15613ba457505f611504565b5f613baf84866142b8565b905083613bbc8683614260565b148390613b555760405162461bcd60e51b815260040161067891906142a6565b5f8183613bfc5760405162461bcd60e51b815260040161067891906142a6565b5061374b8385614260565b604080516101c081019091525f808252602082019081526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001613c6660405180602001604052805f81525090565b8152602001613c8060405180602001604052805f81525090565b8152602001613c9a60405180602001604052805f81525090565b8152602001613cb460405180602001604052805f81525090565b905290565b6001600160a01b03811681146109ca575f80fd5b5f805f60608486031215613cdf575f80fd5b8335613cea81613cb9565b9250602084013591506040840135613d0181613cb9565b809150509250925092565b5f60208284031215613d1c575f80fd5b813561150481613cb9565b5f60208284031215613d37575f80fd5b5035919050565b5f8060408385031215613d4f575f80fd5b8235613d5a81613cb9565b946020939093013593505050565b5f805f60608486031215613d7a575f80fd5b8335613d8581613cb9565b92506020840135613d9581613cb9565b929592945050506040919091013590565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b5f60208284031215613dda575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b6020808252600e908201526d37b7363c9030b236b4b71031b0b760911b604082015260600190565b5f60208284031215613e2d575f80fd5b815161150481613cb9565b80518015158114613e47575f80fd5b919050565b5f60208284031215613e5c575f80fd5b61150482613e38565b634e487b7160e01b5f52604160045260245ffd5b8051613e4781613cb9565b5f6020808385031215613e95575f80fd5b825167ffffffffffffffff80821115613eac575f80fd5b818501915085601f830112613ebf575f80fd5b815181811115613ed157613ed1613e65565b8060051b604051601f19603f83011681018181108582111715613ef657613ef6613e65565b604052918252848201925083810185019188831115613f13575f80fd5b938501935b82851015613f3857613f2985613e79565b84529385019392850192613f18565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215613f6b575f80fd5b505082516020840151604085015160609095015191969095509092509050565b5f8060408385031215613f9c575f80fd5b505080516020909101519092909150565b80516001600160601b0381168114613e47575f80fd5b5f805f805f805f60e0888a031215613fd9575f80fd5b613fe288613e38565b965060208801519550613ff760408901613e38565b9450606088015193506080880151925061401360a08901613fad565b915061402160c08901613e38565b905092959891949750929550565b60208082526022908201527f5641495f4d494e545f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b5f60208284031215614081575f80fd5b61150482613fad565b60208082526022908201527f5641495f4255524e5f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b6020808252602e908201527f5641495f43555252454e545f494e5445524553545f414d4f554e545f43414c4360408201526d155310551253d397d1905253115160921b606082015260800190565b60208082526024908201527f5641495f504153545f494e5445524553545f43414c43554c4154494f4e5f46416040820152631253115160e21b606082015260800190565b60208082526021908201527f5641495f52455041595f524154455f43414c43554c4154494f4e5f4641494c456040820152601160fa1b606082015260800190565b60208082526029908201527f5641495f544f54414c5f52455041595f414d4f554e545f43414c43554c41544960408201526813d397d1905253115160ba1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a5957610a596141e8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f9061374b9083018461420f565b5f8261427a57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52600160045260245ffd5b80820180821115610a5957610a596141e8565b602081525f611504602083018461420f565b8082028115828204841417610a5957610a596141e856fea264697066735822122080a86245007303d8ffeb504fd3d5dd73aaadc2506ee52e55a23d21109f42fc8664736f6c63430008190033", + "deployedBytecode": "0x608060405234801561000f575f80fd5b506004361061028b575f3560e01c8063691e45ac11610161578063b49b1005116100ca578063d24febad11610084578063d24febad146105a1578063e44e6168146105b4578063ee1fa41e146105fa578063f20fd8f41461060e578063f7260d3e1461062d578063f851a44014610640575f80fd5b8063b49b100514610547578063b9ee87261461054f578063c32094c714610557578063c5f956af1461056a578063c7ee005e1461057d578063cbeb2b2814610590575f80fd5b806378c2f9221161011b57806378c2f922146104de5780637a37c5d0146104f15780638129fc1c14610510578063b06bb42614610518578063b2b481bc1461052b578063b2eafc3914610534575f80fd5b8063691e45ac1461046f5780636fe74a211461049d578063718da7ee146104b0578063741de148146104c357806375c3de43146104cd57806376c71ca1146104d5575f80fd5b80633785d1d6116102035780635ce73240116101bd5780635ce732401461040c5780635fe3b5671461041557806360c954ef1461042857806361b3311c146104455780636509795414610458578063657bdf9414610467575f80fd5b80633785d1d6146103a45780633b5a0a64146103b75780633b72fbef146103ca5780634070a0c9146103d35780634576b5db146103e65780634712ee7d146103f9575f80fd5b80631d08837b116102545780631d08837b146103265780631d504dc6146103395780631f040ff51461034c578063234f89771461035f57806324650602146103725780632678224714610391575f80fd5b80623b58841461028f57806304ef9d58146102bf57806311b3d5e7146102d657806313007d55146102fe57806319129e5a14610311575b5f80fd5b6002546102a2906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6102c8600a5481565b6040519081526020016102b6565b6102e96102e4366004613ccd565b610652565b604080519283526020830191909152016102b6565b6014546102a2906001600160a01b031681565b61032461031f366004613d0c565b61074d565b005b610324610334366004613d27565b6107e1565b610324610347366004613d0c565b610854565b6102e961035a366004613d3e565b6109cd565b6102c861036d366004613d0c565b610a2a565b6102c8610380366004613d0c565b60076020525f908152604090205481565b6001546102a2906001600160a01b031681565b6102e96103b2366004613d0c565b610a5f565b6103246103c5366004613d27565b6113a1565b6102c8600c5481565b6103246103e1366004613d27565b611415565b6102c86103f4366004613d0c565b611487565b6102c8610407366004613d27565b61150b565b6102c8600d5481565b6004546102a2906001600160a01b031681565b6006546104359060ff1681565b60405190151581526020016102b6565b610324610453366004613d0c565b611b18565b6102c8670de0b6b3a764000081565b6102c8611baa565b61048261047d366004613d3e565b611c83565b604080519384526020840192909252908201526060016102b6565b6102e96104ab366004613d27565b612120565b6103246104be366004613d0c565b612172565b63042d56006102c8565b6102c86121fe565b6102c860135481565b6102c86104ec366004613d0c565b61224f565b6104f85f81565b6040516001600160601b0390911681526020016102b6565b610324612436565b6003546102a2906001600160a01b031681565b6102c8600f5481565b6008546102a2906001600160a01b031681565b6103246124c9565b6102c86125c3565b610324610565366004613d0c565b612814565b6009546102a2906001600160a01b031681565b6015546102a2906001600160a01b031681565b6016546001600160a01b03166102a2565b6102c86105af366004613d68565b6128a6565b6005546105d6906001600160e01b03811690600160e01b900463ffffffff1682565b604080516001600160e01b03909316835263ffffffff9091166020830152016102b6565b60155461043590600160a01b900460ff1681565b6102c861061c366004613d0c565b60126020525f908152604090205481565b600e546102a2906001600160a01b031681565b5f546102a2906001600160a01b031681565b600b545f90819060ff166106815760405162461bcd60e51b815260040161067890613da6565b60405180910390fd5b600b805460ff19169055610693612a3b565b5f836001600160a01b031663a6afed956040518163ffffffff1660e01b81526004016020604051808303815f875af11580156106d1573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106f59190613dca565b905080156107245761071981600681111561071257610712613de1565b6008612ae8565b5f9250925050610736565b61073033878787612b5f565b92509250505b600b805460ff191660011790559094909350915050565b5f546001600160a01b031633146107765760405162461bcd60e51b815260040161067890613df5565b61077f81613088565b601480546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f0f1eca7612e020f6e4582bcead0573eba4b5f7b56668754c6aed82ef12057dd491015b60405180910390a15050565b6108166040518060400160405280601481526020017373657442617365526174652875696e743235362960601b8152506130d6565b600c80549082905560408051828152602081018490527fc84c32795e68685ec107b0e94ae126ef464095f342c7e2e0fec06a23d2e8677e91016107d5565b806001600160a01b031663f851a4406040518163ffffffff1660e01b8152600401602060405180830381865afa158015610890573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108b49190613e1d565b6001600160a01b0316336001600160a01b0316146109245760405162461bcd60e51b815260206004820152602760248201527f6f6e6c7920756e6974726f6c6c65722061646d696e2063616e206368616e676560448201526620627261696e7360c81b6064820152608401610678565b806001600160a01b031663c1e803346040518163ffffffff1660e01b81526004016020604051808303815f875af1158015610961573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906109859190613dca565b156109ca5760405162461bcd60e51b815260206004820152601560248201527418da185b99d9481b9bdd08185d5d1a1bdc9a5e9959605a1b6044820152606401610678565b50565b600b545f90819060ff166109f35760405162461bcd60e51b815260040161067890613da6565b600b805460ff19169055610a0684613088565b610a108484613183565b91509150600b805460ff1916600117905590939092509050565b6001600160a01b0381165f90815260116020526040812054808203610a595750670de0b6b3a764000092915050565b92915050565b6015545f908190600160a01b900460ff168015610ae55750601554604051630e3da90d60e21b81526001600160a01b038581166004830152909116906338f6a43490602401602060405180830381865afa158015610abf573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ae39190613e4c565b155b15610af5576002935f9350915050565b60048054604051632aff3bff60e21b81526001600160a01b03868116938201939093525f929091169063abfceffc906024015f60405180830381865afa158015610b41573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b689190810190613e84565b90505f60045f9054906101000a90046001600160a01b03166001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bbb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610bdf9190613e1d565b9050610be9613c07565b82515f9081905b808210156110e557858281518110610c0a57610c0a613f44565b60209081029190910101516040516361bfb47160e11b81526001600160a01b038b811660048301529091169063c37f68e290602401608060405180830381865afa158015610c5a573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c7e9190613f58565b60e088015260c087015260a086015280855215610ca75760035b995f9950975050505050505050565b60405180602001604052808560e00151815250846101400181905250846001600160a01b03166388142b6b878481518110610ce457610ce4613f44565b60200260200101516040518263ffffffff1660e01b8152600401610d1791906001600160a01b0391909116815260200190565b6040805180830381865afa158015610d31573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d559190613f8b565b61012086015261010085018190521580610d725750610120840151155b15610d7e576004610c98565b604080516020808201835261010087015182526101608701918252825190810190925261012086015182526101808601919091526101408501519051610dc491906131d1565b85602001866101a001829052826003811115610de257610de2613de1565b6003811115610df357610df3613de1565b9052505f905084602001516003811115610e0f57610e0f613de1565b14610e1b576005610c98565b610e2e846101a001518560a001516132de565b6060860181905260208601826003811115610e4b57610e4b613de1565b6003811115610e5c57610e5c613de1565b9052505f905084602001516003811115610e7857610e78613de1565b14610e84576005610c98565b60045486515f916001600160a01b031690638e8f294b90899086908110610ead57610ead613f44565b60200260200101516040518263ffffffff1660e01b8152600401610ee091906001600160a01b0391909116815260200190565b60e060405180830381865afa158015610efb573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f1f9190613fc3565b5050505050915050610f3585606001518261332b565b6060870181905260208701826003811115610f5257610f52613de1565b6003811115610f6357610f63613de1565b9052505f905085602001516003811115610f7f57610f7f613de1565b14610f975760055b9a5f9a5098505050505050505050565b610fad8560600151670de0b6b3a7640000613368565b6060870181905260208701826003811115610fca57610fca613de1565b6003811115610fdb57610fdb613de1565b9052505f905085602001516003811115610ff757610ff7613de1565b14611003576005610f87565b61101585604001518660600151613387565b604087018190526020870182600381111561103257611032613de1565b600381111561104357611043613de1565b9052505f90508560200151600381111561105f5761105f613de1565b1461106b576005610f87565b6110838561018001518660c0015187608001516133aa565b60808701819052602087018260038111156110a0576110a0613de1565b60038111156110b1576110b1613de1565b9052505f9050856020015160038111156110cd576110cd613de1565b146110d9576005610f87565b50600190910190610bf0565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611132573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111569190613dca565b90505f811561116b576111688b61224f565b90505b611179866080015182613387565b608088018190526020880182600381111561119657611196613de1565b60038111156111a7576111a7613de1565b9052505f9050866020015160038111156111c3576111c3613de1565b146111dc5760055b9b5f9b509950505050505050505050565b61125d866040015160045f9054906101000a90046001600160a01b03166001600160a01b031663bec04f726040518163ffffffff1660e01b8152600401602060405180830381865afa158015611234573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906112589190613dca565b61332b565b8760200181975082600381111561127657611276613de1565b600381111561128757611287613de1565b9052505f9050866020015160038111156112a3576112a3613de1565b146112c05760405162461bcd60e51b81526004016106789061402f565b6112cc85612710613368565b876020018197508260038111156112e5576112e5613de1565b60038111156112f6576112f6613de1565b9052505f90508660200151600381111561131257611312613de1565b1461132f5760405162461bcd60e51b81526004016106789061402f565b61133d858760800151613401565b8760200181975082600381111561135657611356613de1565b600381111561136757611367613de1565b9052505f90508660200151600381111561138357611383613de1565b1461138f5760026111cb565b5f9b949a509398505050505050505050565b6113d760405180604001604052806015815260200174736574466c6f6174526174652875696e743235362960581b8152506130d6565b600d80549082905560408051828152602081018490527f546fb35dbbd92233aecc22b5a11a6791e5db7ec14f62e49cbac2a10c0437f56191016107d5565b611449604051806040016040528060138152602001727365744d696e744361702875696e743235362960681b8152506130d6565b601380549082905560408051828152602081018490527f43862b3eea2df8fce70329f3f84cbcad220f47a73be46c5e00df25165a6e169591016107d5565b5f80546001600160a01b031633146114a557610a5960016002612ae8565b600480546001600160a01b038481166001600160a01b031983168117909355604080519190921680825260208201939093527f7ac369dbd14fa5ea3f473ed67cc9d598964a77501540ba6751eb0b3decf5870d910160405180910390a15f5b9392505050565b600b545f9060ff1661152f5760405162461bcd60e51b815260040161067890613da6565b600b805460ff191690556004546001600160a01b031661155057505f611b06565b60048054604051637376909960e01b815233928101929092525f916001600160a01b0390911690637376909990602401602060405180830381865afa15801561159b573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906115bf9190614071565b6001600160601b0316146116245760405162461bcd60e51b815260206004820152602660248201527f564149206d696e74206f6e6c7920616c6c6f77656420696e2074686520636f726044820152651948141bdbdb60d21b6064820152608401610678565b61162d82613421565b611635612a3b565b61163d6124c9565b601654604080516318160ddd60e01b815290515f9233926001600160a01b0390911691849183916318160ddd916004808201926020929091908290030181865afa15801561168d573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116b19190613dca565b90505f6116be8288613467565b90506013548111156117055760405162461bcd60e51b815260206004820152601060248201526f1b5a5b9d0818d85c081c995858da195960821b6044820152606401610678565b61170e8461349c565b5f61171885610a5f565b909650905085156117755760405162461bcd60e51b815260206004820152602160248201527f636f756c64206e6f7420636f6d70757465206d696e7461626c6520616d6f756e6044820152601d60fa1b6064820152608401610678565b808811156117c55760405162461bcd60e51b815260206004820152601960248201527f6d696e74696e67206d6f7265207468616e20616c6c6f776564000000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b03888116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa158015611812573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906118369190613dca565b90508015611896575f6118488761224f565b90505f6118558284613628565b6001600160a01b0389165f9081526012602052604090205490915061187a9082613467565b6001600160a01b0389165f908152601260205260409020555090505b5f6118a1828b613467565b6004805460405163fd51a3ad60e01b81526001600160a01b038b81169382019390935260248101849052929350169063fd51a3ad906044016020604051808303815f875af11580156118f5573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906119199190613dca565b975087156119615760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f600a545f14611a41575f61198961197b8d600a54613661565b670de0b6b3a76400006136a2565b90506119958c82613628565b6009546040516340c10f1960e01b81526001600160a01b039182166004820152602481018490529193508916906340c10f19906044015f604051808303815f87803b1580156119e2575f80fd5b505af11580156119f4573d5f803e3d5ffd5b5050604080516001600160a01b038d168152602081018590527fb0715a6d41a37c1b0672c22c09a31a0642c1fb3f9efa2d5fd5c6d2d891ee78c6935001905060405180910390a150611a44565b50895b6040516340c10f1960e01b81526001600160a01b038981166004830152602482018390528816906340c10f19906044015f604051808303815f87803b158015611a8b575f80fd5b505af1158015611a9d573d5f803e3d5ffd5b5050600f546001600160a01b038b165f818152601160209081526040918290209390935580519182529181018590527e2e68ab1600fc5e7290e2ceaa79e2f86b4dbaca84a48421e167e0b40409218a935001905060405180910390a15f99505050505050505050505b600b805460ff19166001179055919050565b5f546001600160a01b03163314611b415760405162461bcd60e51b815260040161067890613df5565b601654604080516001600160a01b03928316815291831660208301527fe45150fb0a88e2274ecbca05ddde9925dd64b6e126ae0fa23ee2d42e668a49d3910160405180910390a1601680546001600160a01b0319166001600160a01b0392909216919091179055565b5f611be96040518060400160405280601b81526020017f746f67676c654f6e6c795072696d65486f6c6465724d696e74282900000000008152506130d6565b601554600160a01b900460ff16158015611c0c57506015546001600160a01b0316155b15611c175750600290565b60155460408051600160a01b90920460ff16158015835260208301527f8efa7b6021d602e0cdef814b7435609ee40deb2a0352ca676d10045750516a5f910160405180910390a16015805460ff60a01b198116600160a01b9182900460ff16159091021790555f905090565b5f805f805f611c918761224f565b600480546040516315e3f14f60e11b81526001600160a01b038b8116938201939093529293505f92611d0e9285921690632bc7e29e90602401602060405180830381865afa158015611ce5573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611d099190613dca565b613401565b90935090505f836003811115611d2657611d26613de1565b14611d435760405162461bcd60e51b81526004016106789061408a565b6001600160a01b0388165f90815260126020526040902054611d659082613387565b90935090505f836003811115611d7d57611d7d613de1565b14611d9a5760405162461bcd60e51b81526004016106789061408a565b6001600160a01b0388165f908152601260205260408120548290848a10611dff57611dc58585613401565b90965092505f866003811115611ddd57611ddd613de1565b14611dfa5760405162461bcd60e51b81526004016106789061408a565b61210f565b5f611e128b670de0b6b3a764000061332b565b90975090505f876003811115611e2a57611e2a613de1565b14611e775760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b611e818187613368565b90975090505f876003811115611e9957611e99613de1565b14611ee65760405162461bcd60e51b815260206004820152601b60248201527f5641495f504152545f43414c43554c4154494f4e5f4641494c454400000000006044820152606401610678565b5f611ef18787613401565b90985090505f886003811115611f0957611f09613de1565b14611f625760405162461bcd60e51b8152602060048201526024808201527f5641495f4d494e5445445f414d4f554e545f43414c43554c4154494f4e5f46416044820152631253115160e21b6064820152608401610678565b611f6c818361332b565b90985094505f886003811115611f8457611f84613de1565b14611fa15760405162461bcd60e51b81526004016106789061408a565b611fb385670de0b6b3a7640000613368565b90985094505f886003811115611fcb57611fcb613de1565b14611fe85760405162461bcd60e51b81526004016106789061408a565b611ff2868361332b565b90985093505f88600381111561200a5761200a613de1565b146120275760405162461bcd60e51b8152600401610678906140cc565b61203984670de0b6b3a7640000613368565b90985093505f88600381111561205157612051613de1565b1461206e5760405162461bcd60e51b8152600401610678906140cc565b6001600160a01b038d165f90815260126020526040902054612090908361332b565b90985092505f8860038111156120a8576120a8613de1565b146120c55760405162461bcd60e51b81526004016106789061411a565b6120d783670de0b6b3a7640000613368565b90985092505f8860038111156120ef576120ef613de1565b1461210c5760405162461bcd60e51b81526004016106789061411a565b50505b919750955093505050509250925092565b600b545f90819060ff166121465760405162461bcd60e51b815260040161067890613da6565b600b805460ff1916905561215a3384613183565b91509150600b805460ff191660011790559092909150565b5f546001600160a01b0316331461219b5760405162461bcd60e51b815260040161067890613df5565b6121a481613088565b600e80546001600160a01b038381166001600160a01b031983168117909355604080519190921680825260208201939093527f4df62dd7d9cc4f480a167c19c616ae5d5bb40db6d0c2bc66dba57068225f00d891016107d5565b5f806122086125c3565b90505f8061221a8363042d5600613368565b90925090505f82600381111561223257612232613de1565b146115045760405162461bcd60e51b81526004016106789061415e565b600480546040516315e3f14f60e11b81526001600160a01b03848116938201939093525f9283928392839290911690632bc7e29e90602401602060405180830381865afa1580156122a2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122c69190613dca565b6001600160a01b0386165f90815260126020526040812054919250806122ec8484613401565b90965091505f86600381111561230457612304613de1565b146123215760405162461bcd60e51b81526004016106789061419f565b612330600f54611d098a610a2a565b90965094505f86600381111561234857612348613de1565b146123655760405162461bcd60e51b81526004016106789061419f565b61236f858361332b565b90965090505f86600381111561238757612387613de1565b146123a45760405162461bcd60e51b81526004016106789061419f565b6123b681670de0b6b3a7640000613368565b90965090505f8660038111156123ce576123ce613de1565b146123eb5760405162461bcd60e51b81526004016106789061419f565b6123f58482613387565b90965093505f86600381111561240d5761240d613de1565b1461242a5760405162461bcd60e51b81526004016106789061419f565b50919695505050505050565b5f546001600160a01b0316331461245f5760405162461bcd60e51b815260040161067890613df5565b600f54156124a55760405162461bcd60e51b8152602060048201526013602482015272185b1c9958591e481a5b9a5d1a585b1a5e9959606a1b6044820152606401610678565b670de0b6b3a7640000600f55436010555f19601355600b805460ff19166001179055565b5f806124e36124d66121fe565b60105461125890436141fc565b90925090505f8260038111156124fb576124fb613de1565b146125485760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b61255481600f54613387565b90925090505f82600381111561256c5761256c613de1565b146125b95760405162461bcd60e51b815260206004820152601a60248201527f5641495f494e5445524553545f4143435255455f4641494c45440000000000006044820152606401610678565b600f555043601055565b60048054604080516307dc0d1d60e41b815290515f9384936001600160a01b031692637dc0d1d092818301926020928290030181865afa158015612609573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061262d9190613e1d565b90505f80600c54111561280c57600d5415612802575f826001600160a01b031663fc57d4df6126646016546001600160a01b031690565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401602060405180830381865afa1580156126a6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906126ca9190613dca565b905080670de0b6b3a764000011156127f7575f806126f0670de0b6b3a764000084613401565b90945091505f84600381111561270857612708613de1565b146127255760405162461bcd60e51b81526004016106789061415e565b61273182600d5461332b565b90945091505f84600381111561274957612749613de1565b146127665760405162461bcd60e51b81526004016106789061415e565b61277882670de0b6b3a7640000613368565b90945091505f84600381111561279057612790613de1565b146127ad5760405162461bcd60e51b81526004016106789061415e565b6127b982600c54613387565b90945090505f8460038111156127d1576127d1613de1565b146127ee5760405162461bcd60e51b81526004016106789061415e565b95945050505050565b600c54935050505090565b600c549250505090565b5f9250505090565b5f546001600160a01b0316331461283d5760405162461bcd60e51b815260040161067890613df5565b601554604080516001600160a01b03928316815291831660208301527ffb26401242c61b503dd09c29da64a5d4f451549f574b882a40bcdc64ee68b83c910160405180910390a1601580546001600160a01b0319166001600160a01b0392909216919091179055565b5f80546001600160a01b03163314806128c957506008546001600160a01b031633145b6128e0576128d960016017612ae8565b9050611504565b670de0b6b3a764000082106129375760405162461bcd60e51b815260206004820152601d60248201527f74726561737572792070657263656e7420636170206f766572666c6f770000006044820152606401610678565b6008805460098054600a80546001600160a01b03198086166001600160a01b038c81169182179098559084168a8816179094559087905560408051948616808652602086019490945292949091169290917f29f06ea15931797ebaed313d81d100963dc22cb213cb4ce2737b5a62b1a8b1e8910160405180910390a1604080516001600160a01b038085168252881660208201527f8de763046d7b8f08b6c3d03543de1d615309417842bb5d2d62f110f65809ddac910160405180910390a160408051828152602081018790527f0893f8f4101baaabbeb513f96761e7a36eb837403c82cc651c292a4abdc94ed7910160405180910390a1505f9695505050505050565b600480546040805163084bf5ab60e31b815290516001600160a01b039092169263425fad589282820192602092908290030181865afa158015612a80573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612aa49190613e4c565b15612ae65760405162461bcd60e51b81526020600482015260126024820152711c1c9bdd1bd8dbdb081a5cc81c185d5cd95960721b6044820152606401610678565b565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa0836006811115612b1c57612b1c613de1565b836017811115612b2e57612b2e613de1565b6040805192835260208301919091525f9082015260600160405180910390a182600681111561150457611504613de1565b6004545f9081906001600160a01b03161561307f57612b7c6124c9565b60048054604051632fe3f38f60e11b815230928101929092526001600160a01b03858116602484015288811660448401528781166064840152608483018790525f92911690635fc7e71e9060a4016020604051808303815f875af1158015612be6573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c0a9190613dca565b90508015612c2a57612c1f6002600a836136d4565b5f925092505061307f565b43846001600160a01b0316636c540baf6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612c67573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612c8b9190613dca565b14612c9c57612c1f60026009612ae8565b866001600160a01b0316866001600160a01b031603612cc157612c1f6002600f612ae8565b845f03612cd457612c1f6002600d612ae8565b5f198503612ce857612c1f6002600c612ae8565b5f80612cf5898989613753565b90925090508115612d2957612d1c826006811115612d1557612d15613de1565b6010612ae8565b5f9450945050505061307f565b6004805460405163a78dc77560e01b81526001600160a01b0389811693820193909352602481018490525f928392169063a78dc775906044016040805180830381865afa158015612d7c573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612da09190613f8b565b90925090508115612e195760405162461bcd60e51b815260206004820152603760248201527f5641495f4c49515549444154455f434f4d5054524f4c4c45525f43414c43554c60448201527f4154455f414d4f554e545f5345495a455f4641494c45440000000000000000006064820152608401610678565b6040516370a0823160e01b81526001600160a01b038b811660048301528291908a16906370a0823190602401602060405180830381865afa158015612e60573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612e849190613dca565b1015612ed25760405162461bcd60e51b815260206004820152601c60248201527f5641495f4c49515549444154455f5345495a455f544f4f5f4d554348000000006044820152606401610678565b60405163b2a02ff160e01b81526001600160a01b038c811660048301528b81166024830152604482018390525f91908a169063b2a02ff1906064016020604051808303815f875af1158015612f29573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612f4d9190613dca565b90508015612f945760405162461bcd60e51b81526020600482015260146024820152731d1bdad95b881cd95a5e9d5c994819985a5b195960621b6044820152606401610678565b604080516001600160a01b038e811682528d811660208301528183018790528b1660608201526080810184905290517f42d401f96718a0c42e5cea8108973f0022677b7e2e5f4ee19851b2de7a0394e79181900360a00190a1600480546040516347ef3b3b60e01b815230928101929092526001600160a01b038b811660248401528e811660448401528d811660648401526084830187905260a4830185905216906347ef3b3b9060c4015f604051808303815f87803b158015613056575f80fd5b505af1158015613068573d5f803e3d5ffd5b505f9250613074915050565b975092955050505050505b94509492505050565b6001600160a01b0381166109ca5760405162461bcd60e51b815260206004820152601560248201527463616e2774206265207a65726f206164647265737360581b6044820152606401610678565b6014546040516318c5e8ab60e01b81526001600160a01b03909116906318c5e8ab90613108903390859060040161423d565b602060405180830381865afa158015613123573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906131479190613e4c565b6109ca5760405162461bcd60e51b815260206004820152600d60248201526c1858d8d95cdcc819195b9a5959609a1b6044820152606401610678565b6004545f9081906001600160a01b03166131a157505f9050806131ca565b6131aa83613421565b6131b2612a3b565b6131ba6124c9565b6131c5338585613753565b915091505b9250929050565b5f6131e760405180602001604052805f81525090565b5f806131f9865f0151865f015161332b565b90925090505f82600381111561321157613211613de1565b1461322f575060408051602081019091525f815290925090506131ca565b5f8061324d6132476002670de0b6b3a7640000614260565b84613387565b90925090505f82600381111561326557613265613de1565b14613287578160405180602001604052805f81525095509550505050506131ca565b5f8061329b83670de0b6b3a7640000613368565b90925090505f8260038111156132b3576132b3613de1565b146132c0576132c061427f565b60408051602081019091529081525f9a909950975050505050505050565b5f805f806132ec8686613a99565b90925090505f82600381111561330457613304613de1565b14613314575091505f90506131ca565b5f61331e82613b0e565b9350935050509250929050565b5f80835f0361333e57505f9050806131ca565b8383028361334c8683614260565b1461335e5760025f92509250506131ca565b5f925090506131ca565b5f80825f0361337c5750600190505f6131ca565b5f6131c58486614260565b5f8083830184811061339d575f925090506131ca565b60025f92509250506131ca565b5f805f806133b88787613a99565b90925090505f8260038111156133d0576133d0613de1565b146133e0575091505f90506133f9565b6133f26133ec82613b0e565b86613387565b9350935050505b935093915050565b5f8083831161341657505f90508183036131ca565b50600390505f6131ca565b5f81116109ca5760405162461bcd60e51b8152602060048201526014602482015273616d6f756e742063616e2774206265207a65726f60601b6044820152606401610678565b5f6115048383604051806040016040528060118152602001706164646974696f6e206f766572666c6f7760781b815250613b25565b5f60045f9054906101000a90046001600160a01b03166001600160a01b031663d7c46d2d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156134ed573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906135119190613e1d565b60048054604051632aff3bff60e21b81526001600160a01b03868116938201939093529293505f9291169063abfceffc906024015f60405180830381865afa15801561355f573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526135869190810190613e84565b80519091505f5b8181101561362157836001600160a01b031663a9c3cab18483815181106135b6576135b6613f44565b60200260200101516040518263ffffffff1660e01b81526004016135e991906001600160a01b0391909116815260200190565b5f604051808303815f87803b158015613600575f80fd5b505af1158015613612573d5f803e3d5ffd5b5050505080600101905061358d565b5050505050565b5f6115048383604051806040016040528060158152602001747375627472616374696f6e20756e646572666c6f7760581b815250613b5e565b5f61150483836040518060400160405280601781526020017f6d756c7469706c69636174696f6e206f766572666c6f77000000000000000000815250613b8c565b5f61150483836040518060400160405280600e81526020016d646976696465206279207a65726f60901b815250613bdc565b5f7f45b96fe442630264581b197e84bbada861235052c5a1aadfff9ea4e40a969aa084600681111561370857613708613de1565b84601781111561371a5761371a613de1565b604080519283526020830191909152810184905260600160405180910390a183600681111561374b5761374b613de1565b949350505050565b5f805f805f6137628787611c83565b601654604051632770a7eb60e21b81526001600160a01b038d811660048301526024820186905294975092955090935091909116908190639dc29fac906044015f604051808303815f87803b1580156137b9575f80fd5b505af11580156137cb573d5f803e3d5ffd5b5050600e546040516323b872dd60e01b81526001600160a01b038d811660048301529182166024820152604481018790525f935090841691506323b872dd906064016020604051808303815f875af1158015613829573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061384d9190613e4c565b90506001811515146138a15760405162461bcd60e51b815260206004820152601a60248201527f6661696c656420746f207472616e7366657220564149206665650000000000006044820152606401610678565b600480546040516315e3f14f60e11b81526001600160a01b038c8116938201939093525f9290911690632bc7e29e90602401602060405180830381865afa1580156138ee573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139129190613dca565b90505f6139286139228389613628565b86613628565b6001600160a01b038c165f9081526012602052604090205490915061394d9086613628565b6001600160a01b03808d165f818152601260205260408082209490945560048054945163fd51a3ad60e01b81529081019290925260248201859052929091169063fd51a3ad906044016020604051808303815f875af11580156139b2573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906139d69190613dca565b90508015613a1e5760405162461bcd60e51b815260206004820152601560248201527431b7b6b83a3937b63632b9103932b532b1ba34b7b760591b6044820152606401610678565b5f613a298989613467565b90507f1db858e6f7e1a0d5e92c10c6507d42b3dabfe0a4867fe90c5a14d9963662ef7e8e8e83604051613a7d939291906001600160a01b039384168152919092166020820152604081019190915260600190565b60405180910390a15f9e909d509b505050505050505050505050565b5f613aaf60405180602001604052805f81525090565b5f80613abe865f01518661332b565b90925090505f826003811115613ad657613ad6613de1565b14613af4575060408051602081019091525f815290925090506131ca565b60408051602081019091529081525f969095509350505050565b80515f90610a5990670de0b6b3a764000090614260565b5f80613b318486614293565b90508285821015613b555760405162461bcd60e51b815260040161067891906142a6565b50949350505050565b5f8184841115613b815760405162461bcd60e51b815260040161067891906142a6565b5061374b83856141fc565b5f831580613b98575082155b15613ba457505f611504565b5f613baf84866142b8565b905083613bbc8683614260565b148390613b555760405162461bcd60e51b815260040161067891906142a6565b5f8183613bfc5760405162461bcd60e51b815260040161067891906142a6565b5061374b8385614260565b604080516101c081019091525f808252602082019081526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f81526020015f8152602001613c6660405180602001604052805f81525090565b8152602001613c8060405180602001604052805f81525090565b8152602001613c9a60405180602001604052805f81525090565b8152602001613cb460405180602001604052805f81525090565b905290565b6001600160a01b03811681146109ca575f80fd5b5f805f60608486031215613cdf575f80fd5b8335613cea81613cb9565b9250602084013591506040840135613d0181613cb9565b809150509250925092565b5f60208284031215613d1c575f80fd5b813561150481613cb9565b5f60208284031215613d37575f80fd5b5035919050565b5f8060408385031215613d4f575f80fd5b8235613d5a81613cb9565b946020939093013593505050565b5f805f60608486031215613d7a575f80fd5b8335613d8581613cb9565b92506020840135613d9581613cb9565b929592945050506040919091013590565b6020808252600a90820152691c994b595b9d195c995960b21b604082015260600190565b5f60208284031215613dda575f80fd5b5051919050565b634e487b7160e01b5f52602160045260245ffd5b6020808252600e908201526d37b7363c9030b236b4b71031b0b760911b604082015260600190565b5f60208284031215613e2d575f80fd5b815161150481613cb9565b80518015158114613e47575f80fd5b919050565b5f60208284031215613e5c575f80fd5b61150482613e38565b634e487b7160e01b5f52604160045260245ffd5b8051613e4781613cb9565b5f6020808385031215613e95575f80fd5b825167ffffffffffffffff80821115613eac575f80fd5b818501915085601f830112613ebf575f80fd5b815181811115613ed157613ed1613e65565b8060051b604051601f19603f83011681018181108582111715613ef657613ef6613e65565b604052918252848201925083810185019188831115613f13575f80fd5b938501935b82851015613f3857613f2985613e79565b84529385019392850192613f18565b98975050505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f805f8060808587031215613f6b575f80fd5b505082516020840151604085015160609095015191969095509092509050565b5f8060408385031215613f9c575f80fd5b505080516020909101519092909150565b80516001600160601b0381168114613e47575f80fd5b5f805f805f805f60e0888a031215613fd9575f80fd5b613fe288613e38565b965060208801519550613ff760408901613e38565b9450606088015193506080880151925061401360a08901613fad565b915061402160c08901613e38565b905092959891949750929550565b60208082526022908201527f5641495f4d494e545f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b5f60208284031215614081575f80fd5b61150482613fad565b60208082526022908201527f5641495f4255524e5f414d4f554e545f43414c43554c4154494f4e5f4641494c604082015261115160f21b606082015260800190565b6020808252602e908201527f5641495f43555252454e545f494e5445524553545f414d4f554e545f43414c4360408201526d155310551253d397d1905253115160921b606082015260800190565b60208082526024908201527f5641495f504153545f494e5445524553545f43414c43554c4154494f4e5f46416040820152631253115160e21b606082015260800190565b60208082526021908201527f5641495f52455041595f524154455f43414c43554c4154494f4e5f4641494c456040820152601160fa1b606082015260800190565b60208082526029908201527f5641495f544f54414c5f52455041595f414d4f554e545f43414c43554c41544960408201526813d397d1905253115160ba1b606082015260800190565b634e487b7160e01b5f52601160045260245ffd5b81810381811115610a5957610a596141e8565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f9061374b9083018461420f565b5f8261427a57634e487b7160e01b5f52601260045260245ffd5b500490565b634e487b7160e01b5f52600160045260245ffd5b80820180821115610a5957610a596141e8565b602081525f611504602083018461420f565b8082028115828204841417610a5957610a596141e856fea264697066735822122080a86245007303d8ffeb504fd3d5dd73aaadc2506ee52e55a23d21109f42fc8664736f6c63430008190033", "devdoc": { "author": "Venus", "events": { @@ -1461,7 +1461,7 @@ "storageLayout": { "storage": [ { - "astId": 32180, + "astId": 51690, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "admin", "offset": 0, @@ -1469,7 +1469,7 @@ "type": "t_address" }, { - "astId": 32183, + "astId": 51693, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "pendingAdmin", "offset": 0, @@ -1477,7 +1477,7 @@ "type": "t_address" }, { - "astId": 32186, + "astId": 51696, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "vaiControllerImplementation", "offset": 0, @@ -1485,7 +1485,7 @@ "type": "t_address" }, { - "astId": 32189, + "astId": 51699, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "pendingVAIControllerImplementation", "offset": 0, @@ -1493,23 +1493,23 @@ "type": "t_address" }, { - "astId": 32195, + "astId": 51705, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "comptroller", "offset": 0, "slot": "4", - "type": "t_contract(ComptrollerInterface)4388" + "type": "t_contract(ComptrollerInterface)9671" }, { - "astId": 32206, + "astId": 51716, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "venusVAIState", "offset": 0, "slot": "5", - "type": "t_struct(VenusVAIState)32202_storage" + "type": "t_struct(VenusVAIState)51712_storage" }, { - "astId": 32209, + "astId": 51719, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "isVenusVAIInitialized", "offset": 0, @@ -1517,7 +1517,7 @@ "type": "t_bool" }, { - "astId": 32214, + "astId": 51724, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "venusVAIMinterIndex", "offset": 0, @@ -1525,7 +1525,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 32220, + "astId": 51730, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "treasuryGuardian", "offset": 0, @@ -1533,7 +1533,7 @@ "type": "t_address" }, { - "astId": 32223, + "astId": 51733, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "treasuryAddress", "offset": 0, @@ -1541,7 +1541,7 @@ "type": "t_address" }, { - "astId": 32226, + "astId": 51736, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "treasuryPercent", "offset": 0, @@ -1549,7 +1549,7 @@ "type": "t_uint256" }, { - "astId": 32229, + "astId": 51739, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "_notEntered", "offset": 0, @@ -1557,7 +1557,7 @@ "type": "t_bool" }, { - "astId": 32232, + "astId": 51742, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "baseRateMantissa", "offset": 0, @@ -1565,7 +1565,7 @@ "type": "t_uint256" }, { - "astId": 32235, + "astId": 51745, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "floatRateMantissa", "offset": 0, @@ -1573,7 +1573,7 @@ "type": "t_uint256" }, { - "astId": 32238, + "astId": 51748, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "receiver", "offset": 0, @@ -1581,7 +1581,7 @@ "type": "t_address" }, { - "astId": 32241, + "astId": 51751, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "vaiMintIndex", "offset": 0, @@ -1589,7 +1589,7 @@ "type": "t_uint256" }, { - "astId": 32244, + "astId": 51754, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "accrualBlockNumber", "offset": 0, @@ -1597,7 +1597,7 @@ "type": "t_uint256" }, { - "astId": 32249, + "astId": 51759, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "vaiMinterInterestIndex", "offset": 0, @@ -1605,7 +1605,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 32254, + "astId": 51764, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "pastVAIInterest", "offset": 0, @@ -1613,7 +1613,7 @@ "type": "t_mapping(t_address,t_uint256)" }, { - "astId": 32257, + "astId": 51767, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "mintCap", "offset": 0, @@ -1621,7 +1621,7 @@ "type": "t_uint256" }, { - "astId": 32260, + "astId": 51770, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "accessControl", "offset": 0, @@ -1629,7 +1629,7 @@ "type": "t_address" }, { - "astId": 32266, + "astId": 51776, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "prime", "offset": 0, @@ -1637,7 +1637,7 @@ "type": "t_address" }, { - "astId": 32269, + "astId": 51779, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "mintEnabledOnlyForPrimeHolder", "offset": 20, @@ -1645,7 +1645,7 @@ "type": "t_bool" }, { - "astId": 32275, + "astId": 51785, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "vai", "offset": 0, @@ -1664,7 +1664,7 @@ "label": "bool", "numberOfBytes": "1" }, - "t_contract(ComptrollerInterface)4388": { + "t_contract(ComptrollerInterface)9671": { "encoding": "inplace", "label": "contract ComptrollerInterface", "numberOfBytes": "20" @@ -1676,12 +1676,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_struct(VenusVAIState)32202_storage": { + "t_struct(VenusVAIState)51712_storage": { "encoding": "inplace", "label": "struct VAIControllerStorageG1.VenusVAIState", "members": [ { - "astId": 32198, + "astId": 51708, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "index", "offset": 0, @@ -1689,7 +1689,7 @@ "type": "t_uint224" }, { - "astId": 32201, + "astId": 51711, "contract": "contracts/Tokens/VAI/VAIController.sol:VAIController", "label": "block", "offset": 28, diff --git a/deployments/bsctestnet/solcInputs/39163d4d4ac1a249a8d521dabc3055c5.json b/deployments/bsctestnet/solcInputs/39163d4d4ac1a249a8d521dabc3055c5.json new file mode 100644 index 000000000..1de259488 --- /dev/null +++ b/deployments/bsctestnet/solcInputs/39163d4d4ac1a249a8d521dabc3055c5.json @@ -0,0 +1,592 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./OwnableUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n function __Ownable2Step_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable2Step_init_unchained() internal onlyInitializing {\n }\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n function __Ownable_init() internal onlyInitializing {\n __Ownable_init_unchained();\n }\n\n function __Ownable_init_unchained() internal onlyInitializing {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```solidity\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n *\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized != type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/ContextUpgradeable.sol\";\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract PausableUpgradeable is Initializable, ContextUpgradeable {\n /**\n * @dev Emitted when the pause is triggered by `account`.\n */\n event Paused(address account);\n\n /**\n * @dev Emitted when the pause is lifted by `account`.\n */\n event Unpaused(address account);\n\n bool private _paused;\n\n /**\n * @dev Initializes the contract in unpaused state.\n */\n function __Pausable_init() internal onlyInitializing {\n __Pausable_init_unchained();\n }\n\n function __Pausable_init_unchained() internal onlyInitializing {\n _paused = false;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n modifier whenNotPaused() {\n _requireNotPaused();\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n modifier whenPaused() {\n _requirePaused();\n _;\n }\n\n /**\n * @dev Returns true if the contract is paused, and false otherwise.\n */\n function paused() public view virtual returns (bool) {\n return _paused;\n }\n\n /**\n * @dev Throws if the contract is paused.\n */\n function _requireNotPaused() internal view virtual {\n require(!paused(), \"Pausable: paused\");\n }\n\n /**\n * @dev Throws if the contract is not paused.\n */\n function _requirePaused() internal view virtual {\n require(paused(), \"Pausable: not paused\");\n }\n\n /**\n * @dev Triggers stopped state.\n *\n * Requirements:\n *\n * - The contract must not be paused.\n */\n function _pause() internal virtual whenNotPaused {\n _paused = true;\n emit Paused(_msgSender());\n }\n\n /**\n * @dev Returns to normal state.\n *\n * Requirements:\n *\n * - The contract must be paused.\n */\n function _unpause() internal virtual whenPaused {\n _paused = false;\n emit Unpaused(_msgSender());\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20PermitUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n * doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n * token.safeTransferFrom(msg.sender, address(this), value);\n * ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20PermitUpgradeable {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n *\n * CAUTION: See Security Considerations above.\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\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 amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20Upgradeable.sol\";\nimport \"../extensions/IERC20PermitUpgradeable.sol\";\nimport \"../../../utils/AddressUpgradeable.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20Upgradeable {\n using AddressUpgradeable for address;\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(IERC20Upgradeable token, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, 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(IERC20Upgradeable token, address from, address to, uint256 value) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20Upgradeable token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\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(IERC20Upgradeable token, address spender, uint256 value) internal {\n uint256 oldAllowance = token.allowance(address(this), spender);\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease 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 safeDecreaseAllowance(IERC20Upgradeable token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\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(IERC20Upgradeable token, address spender, uint256 value) internal {\n bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20PermitUpgradeable token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\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(IERC20Upgradeable token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\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(IERC20Upgradeable 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\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && AddressUpgradeable.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport {Initializable} from \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n\n function _contextSuffixLength() internal view virtual returns (uint256) {\n return 0;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCastUpgradeable {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby disabling any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable2Step.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n address private _pendingOwner;\n\n event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Returns the address of the pending owner.\n */\n function pendingOwner() public view virtual returns (address) {\n return _pendingOwner;\n }\n\n /**\n * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual override onlyOwner {\n _pendingOwner = newOwner;\n emit OwnershipTransferStarted(owner(), newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual override {\n delete _pendingOwner;\n super._transferOwnership(newOwner);\n }\n\n /**\n * @dev The new owner accepts the ownership transfer.\n */\n function acceptOwnership() public virtual {\n address sender = _msgSender();\n require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n _transferOwnership(sender);\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1967.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (interfaces/IERC1967.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.\n *\n * _Available since v4.8.3._\n */\ninterface IERC1967 {\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Emitted when the beacon is changed.\n */\n event BeaconUpgraded(address indexed beacon);\n}\n" + }, + "@openzeppelin/contracts/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializing the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/IERC1967.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n */\nabstract contract ERC1967Upgrade is IERC1967 {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(address newImplementation, bytes memory data, bool forceCall) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(address newImplementation, bytes memory data, bool forceCall) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n Address.isContract(IBeacon(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(address newBeacon, bytes memory data, bool forceCall) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overridden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overridden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.3) (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(ITransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(ITransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(ITransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n ITransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev Interface for {TransparentUpgradeableProxy}. In order to implement transparency, {TransparentUpgradeableProxy}\n * does not implement this interface directly, and some of its functions are implemented by an internal dispatch\n * mechanism. The compiler is unaware that these functions are implemented by {TransparentUpgradeableProxy} and will not\n * include them in the ABI so this interface must be used to interact with it.\n */\ninterface ITransparentUpgradeableProxy is IERC1967 {\n function admin() external view returns (address);\n\n function implementation() external view returns (address);\n\n function changeAdmin(address) external;\n\n function upgradeTo(address) external;\n\n function upgradeToAndCall(address, bytes memory) external payable;\n}\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n *\n * NOTE: The real interface of this proxy is that defined in `ITransparentUpgradeableProxy`. This contract does not\n * inherit from that interface, and instead the admin functions are implicitly implemented using a custom dispatch\n * mechanism in `_fallback`. Consequently, the compiler will not produce an ABI for this contract. This is necessary to\n * fully implement transparency without decoding reverts caused by selector clashes between the proxy and the\n * implementation.\n *\n * WARNING: It is not recommended to extend this contract to add additional external functions. If you do so, the compiler\n * will not check that there are no selector conflicts, due to the note above. A selector clash between any new function\n * and the functions declared in {ITransparentUpgradeableProxy} will be resolved in favor of the new one. This could\n * render the admin operations inaccessible, which could prevent upgradeability. Transparency may also be compromised.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(address _logic, address admin_, bytes memory _data) payable ERC1967Proxy(_logic, _data) {\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n *\n * CAUTION: This modifier is deprecated, as it could cause issues if the modified function has arguments, and the\n * implementation provides a function with the same selector.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev If caller is the admin process the call internally, otherwise transparently fallback to the proxy behavior\n */\n function _fallback() internal virtual override {\n if (msg.sender == _getAdmin()) {\n bytes memory ret;\n bytes4 selector = msg.sig;\n if (selector == ITransparentUpgradeableProxy.upgradeTo.selector) {\n ret = _dispatchUpgradeTo();\n } else if (selector == ITransparentUpgradeableProxy.upgradeToAndCall.selector) {\n ret = _dispatchUpgradeToAndCall();\n } else if (selector == ITransparentUpgradeableProxy.changeAdmin.selector) {\n ret = _dispatchChangeAdmin();\n } else if (selector == ITransparentUpgradeableProxy.admin.selector) {\n ret = _dispatchAdmin();\n } else if (selector == ITransparentUpgradeableProxy.implementation.selector) {\n ret = _dispatchImplementation();\n } else {\n revert(\"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n }\n assembly {\n return(add(ret, 0x20), mload(ret))\n }\n } else {\n super._fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function _dispatchAdmin() private returns (bytes memory) {\n _requireZeroValue();\n\n address admin = _getAdmin();\n return abi.encode(admin);\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function _dispatchImplementation() private returns (bytes memory) {\n _requireZeroValue();\n\n address implementation = _implementation();\n return abi.encode(implementation);\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _dispatchChangeAdmin() private returns (bytes memory) {\n _requireZeroValue();\n\n address newAdmin = abi.decode(msg.data[4:], (address));\n _changeAdmin(newAdmin);\n\n return \"\";\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n */\n function _dispatchUpgradeTo() private returns (bytes memory) {\n _requireZeroValue();\n\n address newImplementation = abi.decode(msg.data[4:], (address));\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n\n return \"\";\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n */\n function _dispatchUpgradeToAndCall() private returns (bytes memory) {\n (address newImplementation, bytes memory data) = abi.decode(msg.data[4:], (address, bytes));\n _upgradeToAndCall(newImplementation, data, true);\n\n return \"\";\n }\n\n /**\n * @dev Returns the current admin.\n *\n * CAUTION: This function is deprecated. Use {ERC1967Upgrade-_getAdmin} instead.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev To keep this contract fully transparent, all `ifAdmin` functions must be payable. This helper is here to\n * emulate some proxy functions being non-payable while still allowing value to pass through.\n */\n function _requireZeroValue() private {\n require(msg.value == 0);\n }\n}\n" + }, + "@openzeppelin/contracts/security/ReentrancyGuard.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n constructor() {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return _status == _ENTERED;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(address from, address to, uint256 amount) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(address owner, address spender, uint256 amount) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev 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 amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address from, address to, uint256 amount) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(IERC20 token, address spender, uint256 value) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n /**\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 _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));\n }\n\n /**\n * @dev Decrease 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 safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));\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.encodeWithSelector(token.approve.selector, spender, value);\n\n if (!_callOptionalReturnBool(token, approvalCall)) {\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));\n _callOptionalReturn(token, approvalCall);\n }\n }\n\n /**\n * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.\n * Revert on invalid signature.\n */\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n require(returndata.length == 0 || abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\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\n success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n *\n * Furthermore, `isContract` will also return true if the target contract within\n * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,\n * which only has an effect at the end of a transaction.\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) 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(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (utils/StorageSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```solidity\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, `uint256`._\n * _Available since v4.9 for `string`, `bytes`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n struct StringSlot {\n string value;\n }\n\n struct BytesSlot {\n bytes value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` with member `value` located at `slot`.\n */\n function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `StringSlot` representation of the string storage pointer `store`.\n */\n function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` with member `value` located at `slot`.\n */\n function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.\n */\n function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := store.slot\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\n\nimport \"./IAccessControlManagerV8.sol\";\n\n/**\n * @title AccessControlledV8\n * @author Venus\n * @notice This contract is helper between access control manager and actual contract. This contract further inherited by other contract (using solidity 0.8.13)\n * to integrate access controlled mechanism. It provides initialise methods and verifying access methods.\n */\nabstract contract AccessControlledV8 is Initializable, Ownable2StepUpgradeable {\n /// @notice Access control manager contract\n IAccessControlManagerV8 internal _accessControlManager;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when access control manager contract address is changed\n event NewAccessControlManager(address oldAccessControlManager, address newAccessControlManager);\n\n /// @notice Thrown when the action is prohibited by AccessControlManager\n error Unauthorized(address sender, address calledContract, string methodSignature);\n\n function __AccessControlled_init(address accessControlManager_) internal onlyInitializing {\n __Ownable2Step_init();\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n function __AccessControlled_init_unchained(address accessControlManager_) internal onlyInitializing {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Sets the address of AccessControlManager\n * @dev Admin function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n * @custom:event Emits NewAccessControlManager event\n * @custom:access Only Governance\n */\n function setAccessControlManager(address accessControlManager_) external onlyOwner {\n _setAccessControlManager(accessControlManager_);\n }\n\n /**\n * @notice Returns the address of the access control manager contract\n */\n function accessControlManager() external view returns (IAccessControlManagerV8) {\n return _accessControlManager;\n }\n\n /**\n * @dev Internal function to set address of AccessControlManager\n * @param accessControlManager_ The new address of the AccessControlManager\n */\n function _setAccessControlManager(address accessControlManager_) internal {\n require(address(accessControlManager_) != address(0), \"invalid acess control manager address\");\n address oldAccessControlManager = address(_accessControlManager);\n _accessControlManager = IAccessControlManagerV8(accessControlManager_);\n emit NewAccessControlManager(oldAccessControlManager, accessControlManager_);\n }\n\n /**\n * @notice Reverts if the call is not allowed by AccessControlManager\n * @param signature Method signature\n */\n function _checkAccessAllowed(string memory signature) internal view {\n bool isAllowedToCall = _accessControlManager.isAllowedToCall(msg.sender, signature);\n\n if (!isAllowedToCall) {\n revert Unauthorized(msg.sender, address(this), signature);\n }\n }\n}\n" + }, + "@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport \"@openzeppelin/contracts/access/IAccessControl.sol\";\n\n/**\n * @title IAccessControlManagerV8\n * @author Venus\n * @notice Interface implemented by the `AccessControlManagerV8` contract.\n */\ninterface IAccessControlManagerV8 is IAccessControl {\n function giveCallPermission(address contractAddress, string calldata functionSig, address accountToPermit) external;\n\n function revokeCallPermission(\n address contractAddress,\n string calldata functionSig,\n address accountToRevoke\n ) external;\n\n function isAllowedToCall(address account, string calldata functionSig) external view returns (bool);\n\n function hasPermission(\n address account,\n address contractAddress,\n string calldata functionSig\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/DeviationBoundedOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { VBep20Interface } from \"./interfaces/VBep20Interface.sol\";\nimport { ResilientOracleInterface } from \"./interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"./interfaces/IDeviationBoundedOracle.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { EXP_SCALE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { ensureNonzeroAddress, ensureNonzeroValue } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { Transient } from \"./lib/Transient.sol\";\n\n/**\n * @title DeviationBoundedOracle\n * @author Venus\n * @notice The DeviationBoundedOracle provides manipulation-resistant pricing for lending operations.\n *\n * It maintains a per-market rolling min/max price window. When the current spot price deviates\n * significantly from the window bounds, protection mode activates automatically and conservative\n * pricing kicks in:\n * - Collateral is valued at min(spot, windowMin) — caps collateral value at recent window low\n * - Debt is valued at max(spot, windowMax) — floors debt value at recent window high\n *\n * This protects against instantaneous or short-duration price manipulation attacks on low-liquidity\n * collateral tokens. Sustained attacks beyond the window period are expected to be handled by\n * off-chain monitoring systems.\n *\n * The oracle exposes both view and non-view price functions. The non-view variants update the\n * price window and trigger protection. The view variants read stored state only. A transient\n * price cache avoids redundant ResilientOracle calls within the same transaction when\n * updateProtectionState is called before the view price reads.\n */\ncontract DeviationBoundedOracle is AccessControlledV8, IDeviationBoundedOracle {\n /// @notice Minimum allowed threshold value (5%) to account for keeper deadband\n uint256 public constant MIN_THRESHOLD = 5e16;\n\n /// @notice Maximum allowed threshold value (50%)\n uint256 public constant MAX_THRESHOLD = 50e16;\n\n /// @notice Keeper deadband threshold (5%) — min/max corrections below this are suppressed\n uint256 public constant KEEPER_DEADBAND = 5e16;\n\n /// @notice Resilient Oracle used to fetch spot prices\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n ResilientOracleInterface public immutable RESILIENT_ORACLE;\n\n /// @notice Native market address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable nativeMarket;\n\n /// @notice VAI address\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vai;\n\n /// @notice Transient storage slot for caching final collateral prices within a transaction\n /// @dev custom:storage-location erc7201:venus-protocol/oracle/DeviationBoundedOracle/cache\n /// keccak256(abi.encode(uint256(keccak256(\"venus-protocol/oracle/DeviationBoundedOracle/cache\")) - 1))\n /// & ~bytes32(uint256(0xff))\n bytes32 public constant COLLATERAL_PRICE_CACHE_SLOT =\n 0x818cfa9b1e1b1cc716656acdb79a94121ed79bfb196bf958683ed2a3277cb200;\n\n /// @notice Transient storage slot for caching final debt prices within a transaction\n /// @dev custom:storage-location erc7201:venus-protocol/oracle/DeviationBoundedOracle/debtCache\n /// keccak256(abi.encode(uint256(keccak256(\"venus-protocol/oracle/DeviationBoundedOracle/debtCache\")) - 1))\n /// & ~bytes32(uint256(0xff))\n bytes32 public constant DEBT_PRICE_CACHE_SLOT = 0x84d6ca795decc666d3d1d524cbbadd8a1e0e0279db766fe7a1b41b1eb8970600;\n\n /// @notice Set this as asset address for Native token on each chain.This is the underlying for vBNB (on bsc)\n /// and can serve as any underlying asset of a market that supports native tokens\n address public constant NATIVE_TOKEN_ADDR = 0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB;\n\n /// @notice Per-asset protection state\n mapping(address => MarketProtectionState) public assetProtectionConfig;\n\n /// @notice Append-only array of all assets ever initialized, used for enumeration\n address[] public allAssets;\n\n /// @notice Storage gap for upgrades\n uint256[48] private __gap;\n\n /**\n * @notice Constructor for the implementation contract. Sets immutable variables.\n * @param _resilientOracle Address of the ResilientOracle contract\n * @param nativeMarketAddress The address of a native market (for bsc it would be vBNB address)\n * @param vaiAddress The address of the VAI token, or address(0) if VAI is not deployed on the chain.\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(ResilientOracleInterface _resilientOracle, address nativeMarketAddress, address vaiAddress) {\n ensureNonzeroAddress(address(_resilientOracle));\n ensureNonzeroAddress(nativeMarketAddress);\n RESILIENT_ORACLE = _resilientOracle;\n nativeMarket = nativeMarketAddress;\n vai = vaiAddress;\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract admin\n * @param accessControlManager_ Address of the access control manager contract\n */\n function initialize(address accessControlManager_) external initializer {\n __AccessControlled_init(accessControlManager_);\n }\n\n // ----- Non-view price functions (update window + trigger protection) -----\n\n /**\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\n * @dev Fetches spot from ResilientOracle, updates the price window, checks trigger,\n * and returns the conservative (lower) price when protection is active.\n * Used by keepers or direct callers who want atomic update + read.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice) {\n (collateralPrice, ) = _updateAndGetBoundedPrices(vToken);\n }\n\n /**\n * @notice Gets the bounded debt price for a given vToken, updating protection state\n * @dev Fetches spot from ResilientOracle, updates the price window, checks trigger,\n * and returns the conservative (higher) price when protection is active.\n * Used by keepers or direct callers who want atomic update + read.\n * @param vToken vToken address\n * @return debtPrice The bounded debt price\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice) {\n (, debtPrice) = _updateAndGetBoundedPrices(vToken);\n }\n\n /**\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\n * @dev Fetches spot from ResilientOracle, updates the price window, checks trigger,\n * and returns both conservative prices in a single call.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @return debtPrice The bounded debt price\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice) {\n return _updateAndGetBoundedPrices(vToken);\n }\n\n /**\n * @notice Fetches the spot price, updates the protection window, and caches the resolved\n * bounded prices in transient storage for the duration of the transaction.\n * @dev Call this once per vToken at the start of a transaction (e.g. from PolicyFacet before\n * liquidity calculations). Subsequent calls to getBoundedCollateralPriceView /\n * getBoundedDebtPriceView within the same transaction will read from the transient cache\n * instead of querying ResilientOracle again, keeping those functions as `view` and\n * avoiding redundant oracle calls.\n * @param vToken vToken address\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function updateProtectionState(address vToken) external {\n _updateAndGetBoundedPrices(vToken);\n }\n\n // ----- View price functions (read stored/cached state only) -----\n\n /**\n * @notice Gets the bounded collateral price for a given vToken (view variant)\n * @dev Reads from transient cache first (populated by a prior updateProtectionState call\n * in the same transaction). Falls back to ResilientOracle on cache miss.\n * Returns min(spot, windowMin) when protection is active, spot otherwise.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n */\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 collateralPrice) {\n (collateralPrice, ) = _computeBoundedPrices(vToken);\n }\n\n /**\n * @notice Gets the bounded debt price for a given vToken (view variant)\n * @dev Reads from transient cache first (populated by a prior updateProtectionState call\n * in the same transaction). Falls back to ResilientOracle on cache miss.\n * Returns max(spot, windowMax) when protection is active, spot otherwise.\n * @param vToken vToken address\n * @return debtPrice The bounded debt price\n */\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 debtPrice) {\n (, debtPrice) = _computeBoundedPrices(vToken);\n }\n\n /**\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @return debtPrice The bounded debt price\n */\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice) {\n return _computeBoundedPrices(vToken);\n }\n\n // ----- Keeper functions -----\n\n /**\n * @notice Updates the minimum price in the rolling window for a given asset\n * @dev Called by the keeper to push corrected min values from the off-chain sliding window.\n * Constraint: newMin must be at or below the current spot price.\n * @param asset The underlying asset address\n * @param newMin The new minimum price\n * @custom:access Only authorized keeper addresses\n * @custom:event MinPriceUpdated\n */\n function updateMinPrice(address asset, uint128 newMin) external {\n _checkAccessAllowed(\"updateMinPrice(address,uint128)\");\n _validateAndUpdateBound(asset, newMin, PriceBoundType.MIN);\n }\n\n /**\n * @notice Updates the maximum price in the rolling window for a given asset\n * @dev Called by the keeper to push corrected max values from the off-chain sliding window.\n * Constraint: newMax must be at or above the current spot price.\n * @param asset The underlying asset address\n * @param newMax The new maximum price\n * @custom:access Only authorized keeper addresses\n * @custom:event MaxPriceUpdated\n */\n function updateMaxPrice(address asset, uint128 newMax) external {\n _checkAccessAllowed(\"updateMaxPrice(address,uint128)\");\n _validateAndUpdateBound(asset, newMax, PriceBoundType.MAX);\n }\n\n /**\n * @notice Exits protection mode for a given asset\n * @dev Called by the keeper/monitor after confirming price has normalised.\n * Enforces two conditions on-chain:\n * 1. Cooldown period has elapsed since the last trigger\n * 2. Price range has converged below the exit threshold\n * @param asset The underlying asset address\n * @custom:access Only authorized monitor/keeper addresses\n * @custom:error ProtectedPriceInactive if protection is not currently active\n * @custom:error CooldownNotElapsed if cooldown period has not elapsed\n * @custom:error PriceRangeNotConverged if window range is still above exit threshold\n * @custom:event ProtectionModeExited\n */\n function exitProtectionMode(address asset) external {\n _checkAccessAllowed(\"exitProtectionMode(address)\");\n ensureNonzeroAddress(asset);\n MarketProtectionState storage state = _ensureInitialized(asset);\n\n if (!state.currentlyUsingProtectedPrice) revert ProtectedPriceInactive(asset);\n\n if (block.timestamp < uint256(state.lastProtectionTriggeredAt) + uint256(state.cooldownPeriod)) {\n revert CooldownNotElapsed(asset, state.lastProtectionTriggeredAt, state.cooldownPeriod);\n }\n\n // exit protected price if price range has converged below exit threshold\n uint256 rangeRatio = _computePriceBoundRatio(state.minPrice, state.maxPrice);\n if (rangeRatio >= state.resetThreshold) {\n revert PriceRangeNotConverged(asset, rangeRatio, state.resetThreshold);\n }\n\n state.currentlyUsingProtectedPrice = false;\n state.lastProtectionTriggeredAt = 0;\n emit ProtectionModeExited(asset);\n }\n\n // ----- Admin functions (governance-gated) -----\n\n /**\n * @notice Initializes protection for a new asset\n * @param asset The underlying asset address\n * @param cooldownPeriod Minimum time protection stays active after last trigger\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\n * @custom:access Only Governance\n * @custom:event ProtectionInitialized\n * @custom:event BoundedPricingWhitelistUpdated\n */\n function setTokenConfig(\n address asset,\n uint64 cooldownPeriod,\n uint256 triggerThreshold,\n uint256 resetThreshold,\n bool enableBoundedPricing\n ) external {\n _checkAccessAllowed(\"setTokenConfig(address,uint64,uint256,uint256,bool)\");\n _setTokenConfig(asset, cooldownPeriod, triggerThreshold, resetThreshold, enableBoundedPricing);\n }\n\n /**\n * @notice Batch-initializes protection for multiple assets in a single transaction\n * @param assets Array of underlying asset addresses\n * @param cooldownPeriods Array of cooldown periods (seconds)\n * @param triggerThresholds Array of trigger thresholds (mantissa)\n * @param resetThresholds Array of reset thresholds (mantissa)\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\n * @custom:access Only Governance\n * @custom:error InvalidArrayLength if array lengths do not match\n * @custom:event ProtectionInitialized for each asset\n * @custom:event BoundedPricingWhitelistUpdated for each asset\n */\n function setTokenConfigs(\n address[] calldata assets,\n uint64[] calldata cooldownPeriods,\n uint256[] calldata triggerThresholds,\n uint256[] calldata resetThresholds,\n bool[] calldata enableBoundedPricings\n ) external {\n _checkAccessAllowed(\"setTokenConfigs(address[],uint64[],uint256[],uint256[],bool[])\");\n uint256 len = assets.length;\n if (\n len == 0 ||\n len != cooldownPeriods.length ||\n len != triggerThresholds.length ||\n len != resetThresholds.length ||\n len != enableBoundedPricings.length\n ) revert InvalidArrayLength();\n\n for (uint256 i; i < len; ++i) {\n _setTokenConfig(\n assets[i],\n cooldownPeriods[i],\n triggerThresholds[i],\n resetThresholds[i],\n enableBoundedPricings[i]\n );\n }\n }\n\n /**\n * @notice Sets the cooldown period for an asset\n * @param asset The underlying asset address\n * @param newCooldown The new cooldown period in seconds\n * @custom:access Only Governance\n * @custom:event CooldownPeriodSet\n */\n function setCooldownPeriod(address asset, uint64 newCooldown) external {\n _checkAccessAllowed(\"setCooldownPeriod(address,uint64)\");\n ensureNonzeroAddress(asset);\n ensureNonzeroValue(newCooldown);\n\n MarketProtectionState storage state = _ensureInitialized(asset);\n emit CooldownPeriodSet(asset, state.cooldownPeriod, newCooldown);\n state.cooldownPeriod = newCooldown;\n }\n\n /**\n * @notice Sets the trigger and reset thresholds for an asset\n * @param asset The underlying asset address\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\n * @custom:access Only Governance\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\n * @custom:event TriggerThresholdSet if the trigger threshold changed\n * @custom:event ResetThresholdSet if the reset threshold changed\n */\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external {\n _checkAccessAllowed(\"setThresholds(address,uint256,uint256)\");\n ensureNonzeroAddress(asset);\n ensureNonzeroValue(newTriggerThreshold);\n ensureNonzeroValue(newResetThreshold);\n if (newTriggerThreshold < MIN_THRESHOLD) revert ThresholdBelowMinimum(newTriggerThreshold, MIN_THRESHOLD);\n if (newTriggerThreshold > MAX_THRESHOLD) revert ThresholdAboveMaximum(newTriggerThreshold, MAX_THRESHOLD);\n if (newResetThreshold >= newTriggerThreshold) revert InvalidResetThreshold(newResetThreshold);\n MarketProtectionState storage state = _ensureInitialized(asset);\n\n if (newTriggerThreshold != state.triggerThreshold) {\n emit TriggerThresholdSet(asset, state.triggerThreshold, newTriggerThreshold);\n state.triggerThreshold = uint128(newTriggerThreshold);\n }\n if (newResetThreshold != state.resetThreshold) {\n emit ResetThresholdSet(asset, state.resetThreshold, newResetThreshold);\n state.resetThreshold = uint128(newResetThreshold);\n }\n }\n\n /**\n * @notice Sets whether an asset is enabled for bounded pricing\n * @param asset The underlying asset address\n * @param enabled Whether bounded pricing should be enabled for the asset\n * @custom:access Only Governance\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\n * @custom:event BoundedPricingWhitelistUpdated\n */\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external {\n _checkAccessAllowed(\"setAssetBoundedPricingEnabled(address,bool)\");\n ensureNonzeroAddress(asset);\n\n MarketProtectionState storage state = _ensureInitialized(asset);\n\n if (!enabled && state.currentlyUsingProtectedPrice) {\n revert ProtectedPriceActive(asset);\n }\n\n if (state.isBoundedPricingEnabled == enabled) return;\n\n // reset the window if re-enabling\n if (enabled) {\n uint128 spotU128 = _safeToUint128(_fetchSpotPrice(asset));\n _setMinPrice(state, asset, spotU128);\n _setMaxPrice(state, asset, spotU128);\n }\n\n state.isBoundedPricingEnabled = enabled;\n emit BoundedPricingWhitelistUpdated(asset, enabled);\n }\n\n // ----- View helpers -----\n\n /**\n * @notice Returns all asset addresses that have ever been initialized\n * @return Array of all initialized asset addresses\n */\n function getInitializedAssets() external view returns (address[] memory) {\n return allAssets;\n }\n\n /**\n * @notice Checks if an asset is whitelisted for bounded pricing\n * @param asset The underlying asset address\n * @return True if the asset is whitelisted\n */\n function isBoundedPricingEnabled(address asset) external view returns (bool) {\n return assetProtectionConfig[asset].isBoundedPricingEnabled;\n }\n\n /**\n * @notice Checks if the asset is currently using the protected (bounded) price\n * @param asset The underlying asset address\n * @return True if the asset is currently using the protected price instead of spot\n */\n function currentlyUsingProtectedPrice(address asset) external view returns (bool) {\n return assetProtectionConfig[asset].currentlyUsingProtectedPrice;\n }\n\n /**\n * @notice Returns all currently whitelisted asset addresses\n * @dev Iterates the append-only allAssets array and filters by isBoundedPricingEnabled.\n * Gas-free for off-chain callers.\n * @return result Array of whitelisted asset addresses\n */\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory) {\n uint256 len = allAssets.length;\n address[] memory temp = new address[](len);\n uint256 count;\n for (uint256 i; i < len; ++i) {\n if (assetProtectionConfig[allAssets[i]].isBoundedPricingEnabled) {\n temp[count++] = allAssets[i];\n }\n }\n address[] memory result = new address[](count);\n for (uint256 i; i < count; ++i) {\n result[i] = temp[i];\n }\n return result;\n }\n\n /**\n * @notice Checks if protection can be exited for an asset\n * @dev Returns true when both conditions are met:\n * 1. Cooldown period has elapsed since last trigger\n * 2. Price range has converged below exit threshold\n * @param asset The underlying asset address\n * @return True if protection can be disabled\n */\n function canExitProtection(address asset) external view returns (bool) {\n MarketProtectionState storage state = assetProtectionConfig[asset];\n return\n state.currentlyUsingProtectedPrice &&\n block.timestamp >= uint256(state.lastProtectionTriggeredAt) + uint256(state.cooldownPeriod) &&\n _computePriceBoundRatio(state.minPrice, state.maxPrice) < state.resetThreshold;\n }\n\n /**\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the deadband\n * from the keeper's proposed window values\n * @dev Allows the keeper to identify stale windows in a single call, avoiding N individual reads.\n * Drift formula: |onChain - proposed| / onChain (scaled by EXP_SCALE)\n * @param assets Array of asset addresses to check\n * @param proposedMins Keeper's off-chain window minimum prices\n * @param proposedMaxs Keeper's off-chain window maximum prices\n * @return needsMinUpdate Whether minPrice drift exceeds deadband for each asset\n * @return needsMaxUpdate Whether maxPrice drift exceeds deadband for each asset\n * @custom:error InvalidArrayLength if the input array lengths do not match\n */\n function checkAndGetWindowDrift(\n address[] calldata assets,\n uint128[] calldata proposedMins,\n uint128[] calldata proposedMaxs\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate) {\n uint256 len = assets.length;\n if (len != proposedMins.length || len != proposedMaxs.length) revert InvalidArrayLength();\n\n needsMinUpdate = new bool[](len);\n needsMaxUpdate = new bool[](len);\n\n for (uint256 i; i < len; ++i) {\n MarketProtectionState storage state = assetProtectionConfig[assets[i]];\n needsMinUpdate[i] = _exceedsCorrectionDeadband(state.minPrice, proposedMins[i]);\n needsMaxUpdate[i] = _exceedsCorrectionDeadband(state.maxPrice, proposedMaxs[i]);\n }\n }\n\n // ----- Internal functions -----\n\n /**\n * @notice Initializes protection parameters and price window for a single asset\n * @dev Fetches the current spot price from ResilientOracle to seed the initial min/max window,\n * confirming the oracle is live for this asset before it is listed. Both bounds start at\n * spot so the window expands naturally as prices move. Can only be called once per asset.\n * @param asset The underlying asset address\n * @param cooldownPeriod Minimum time protection stays active after last trigger\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\n * @custom:error VAINotAllowed if asset is the VAI token\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n */\n function _setTokenConfig(\n address asset,\n uint64 cooldownPeriod,\n uint256 triggerThreshold,\n uint256 resetThreshold,\n bool enableBoundedPricing\n ) internal {\n ensureNonzeroAddress(asset);\n ensureNonzeroValue(cooldownPeriod);\n ensureNonzeroValue(triggerThreshold);\n ensureNonzeroValue(resetThreshold);\n if (assetProtectionConfig[asset].asset != address(0)) revert MarketAlreadyInitialized(asset);\n if (triggerThreshold < MIN_THRESHOLD) revert ThresholdBelowMinimum(triggerThreshold, MIN_THRESHOLD);\n if (triggerThreshold > MAX_THRESHOLD) revert ThresholdAboveMaximum(triggerThreshold, MAX_THRESHOLD);\n if (resetThreshold >= triggerThreshold) revert InvalidResetThreshold(resetThreshold);\n if (asset == vai) revert VAINotAllowed();\n\n uint128 spotU128 = _safeToUint128(_fetchSpotPrice(asset));\n\n assetProtectionConfig[asset] = MarketProtectionState({\n minPrice: spotU128,\n maxPrice: spotU128,\n currentlyUsingProtectedPrice: false,\n isBoundedPricingEnabled: enableBoundedPricing,\n lastProtectionTriggeredAt: 0,\n cooldownPeriod: cooldownPeriod,\n asset: asset,\n triggerThreshold: uint128(triggerThreshold),\n resetThreshold: uint128(resetThreshold)\n });\n\n allAssets.push(asset);\n\n emit ProtectionInitialized(asset, spotU128, spotU128, cooldownPeriod, triggerThreshold);\n emit BoundedPricingWhitelistUpdated(asset, enableBoundedPricing);\n }\n\n /**\n * @notice Validates and applies a keeper-provided min or max price update\n * @param asset The underlying asset address\n * @param newPrice The new price value to set\n * @param boundType Whether this is a MIN or MAX bound update\n * @custom:error ZeroPriceNotAllowed if newPrice is zero\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error InvalidMinPrice if boundType is MIN and newPrice exceeds the current spot or is at or above maxPrice\n * @custom:error InvalidMaxPrice if boundType is MAX and newPrice is below the current spot or is at or below minPrice\n */\n function _validateAndUpdateBound(address asset, uint128 newPrice, PriceBoundType boundType) internal {\n ensureNonzeroAddress(asset);\n if (newPrice == 0) revert ZeroPriceNotAllowed();\n MarketProtectionState storage state = _ensureInitialized(asset);\n\n uint256 currentSpot = _fetchSpotPrice(asset);\n if (boundType == PriceBoundType.MIN) {\n if (newPrice >= state.maxPrice || uint256(newPrice) > currentSpot)\n revert InvalidMinPrice(asset, newPrice, currentSpot);\n _setMinPrice(state, asset, newPrice);\n } else if (boundType == PriceBoundType.MAX) {\n if (newPrice <= state.minPrice || uint256(newPrice) < currentSpot)\n revert InvalidMaxPrice(asset, newPrice, currentSpot);\n _setMaxPrice(state, asset, newPrice);\n }\n }\n\n /**\n * @notice Shared non-view logic for all bounded price functions.\n * Fetches spot, updates window, triggers protection if needed, and returns both bounded prices.\n * @param vToken vToken address\n * @return minPrice The bounded lower (collateral) price\n * @return maxPrice The bounded upper (debt) price\n */\n function _updateAndGetBoundedPrices(address vToken) internal returns (uint256 minPrice, uint256 maxPrice) {\n address asset = _getUnderlyingAsset(vToken);\n\n // Early return if both prices were cached by a prior updateProtectionState call in this tx\n (minPrice, maxPrice) = _getCachedPrices(asset);\n if (minPrice != 0 && maxPrice != 0) return (minPrice, maxPrice);\n\n // return early if failure from resilient oracle to prevent cold SLOAD\n uint256 spot = _fetchSpotPrice(asset);\n MarketProtectionState storage state = assetProtectionConfig[asset];\n if (!state.isBoundedPricingEnabled) {\n _setCachedPrices(asset, spot, spot);\n return (spot, spot);\n }\n (uint128 updatedMin, uint128 updatedMax, bool windowExpanded) = _expandPriceWindow(state, spot, asset);\n bool protectionActive = _checkAndTriggerProtection(state, spot, asset, windowExpanded);\n (minPrice, maxPrice) = _resolveBoundedPrices(protectionActive, spot, uint256(updatedMin), uint256(updatedMax));\n _setCachedPrices(asset, minPrice, maxPrice);\n }\n\n /**\n * @dev Expands the price window toward extremes if the spot price is a new min or max\n * @param state The market protection state\n * @param spot The current spot price\n * @param asset The underlying asset address (for event emission)\n */\n function _expandPriceWindow(\n MarketProtectionState storage state,\n uint256 spot,\n address asset\n ) internal returns (uint128, uint128, bool) {\n uint128 spotU128 = _safeToUint128(spot);\n uint128 currentMin = state.minPrice;\n uint128 currentMax = state.maxPrice;\n bool windowExpanded;\n if (spotU128 < currentMin) {\n _setMinPrice(state, asset, spotU128);\n currentMin = spotU128;\n windowExpanded = true;\n }\n if (spotU128 > currentMax) {\n _setMaxPrice(state, asset, spotU128);\n currentMax = spotU128;\n windowExpanded = true;\n }\n return (currentMin, currentMax, windowExpanded);\n }\n\n /**\n * @dev Checks if the spot price has deviated beyond the threshold and triggers protection.\n * `lastProtectionTriggeredAt` is reset only on the first trigger or when the price has made a\n * genuine new extreme this update (windowExpanded == true). Recovery within the existing window\n * keeps the cooldown ticking so `exitProtectionMode` remains reachable.\n * @param state The market protection state\n * @param spot The current spot price\n * @param asset The underlying asset address (for event emission)\n * @param windowExpanded True if `_expandPriceWindow` recorded a new low or new high this call\n */\n function _checkAndTriggerProtection(\n MarketProtectionState storage state,\n uint256 spot,\n address asset,\n bool windowExpanded\n ) internal returns (bool triggered) {\n if (_exceedsDeviationThreshold(spot, state.minPrice, state.maxPrice, state.triggerThreshold)) {\n bool enteringProtection = !state.currentlyUsingProtectedPrice;\n if (enteringProtection || windowExpanded) {\n state.lastProtectionTriggeredAt = uint64(block.timestamp);\n }\n if (enteringProtection) {\n state.currentlyUsingProtectedPrice = true;\n }\n emit ProtectionTriggered(asset, spot, state.minPrice, state.maxPrice);\n return true;\n }\n if (state.currentlyUsingProtectedPrice) return true;\n }\n\n /**\n * @notice Resolves the final bounded collateral and debt prices given a spot, window bounds, and protection flag.\n * @dev When protection is active: collateral = min(spot, windowMin), debt = max(spot, windowMax).\n * When protection is inactive: both return spot.\n * @param protectionActive Whether the market protection window is currently active\n * @param spot The current spot price\n * @param windowMin The lower bound of the price window\n * @param windowMax The upper bound of the price window\n * @return minPrice The resolved lower-bound (collateral) price\n * @return maxPrice The resolved upper-bound (debt) price\n */\n function _resolveBoundedPrices(\n bool protectionActive,\n uint256 spot,\n uint256 windowMin,\n uint256 windowMax\n ) internal pure returns (uint256, uint256) {\n if (!protectionActive) return (spot, spot);\n return (spot < windowMin ? spot : windowMin, spot > windowMax ? spot : windowMax);\n }\n\n /**\n * @notice Shared view logic for all bounded price view functions.\n * Checks transient cache first for an early return; on miss, fetches from oracle\n * and computes both prices without state mutations.\n * @param vToken vToken address\n * @return minPrice The bounded lower (collateral) price\n * @return maxPrice The bounded upper (debt) price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\n */\n function _computeBoundedPrices(address vToken) internal view returns (uint256 minPrice, uint256 maxPrice) {\n address asset = _getUnderlyingAsset(vToken);\n\n // Early return if both prices were cached by a prior updateProtectionState call in this tx\n (minPrice, maxPrice) = _getCachedPrices(asset);\n if (minPrice != 0 && maxPrice != 0) return (minPrice, maxPrice);\n\n // Cache miss — fetch from oracle and compute without state mutations\n uint256 spot = _fetchSpotPrice(asset);\n MarketProtectionState storage state = assetProtectionConfig[asset];\n if (!state.isBoundedPricingEnabled) return (spot, spot);\n\n // Mirror _expandPriceWindow logic: compute what the window would be after expansion\n uint128 spotU128 = _safeToUint128(spot);\n uint128 windowMin128 = spot < uint256(state.minPrice) ? spotU128 : state.minPrice;\n uint128 windowMax128 = spot > uint256(state.maxPrice) ? spotU128 : state.maxPrice;\n\n bool shouldProtect = state.currentlyUsingProtectedPrice ||\n _exceedsDeviationThreshold(spot, windowMin128, windowMax128, state.triggerThreshold);\n\n (minPrice, maxPrice) = _resolveBoundedPrices(shouldProtect, spot, uint256(windowMin128), uint256(windowMax128));\n }\n\n /**\n * @dev Computes the relative spread between the price window bounds as a ratio scaled by EXP_SCALE.\n * Formula: \\((maxPrice - minPrice) / minPrice\\), scaled by `EXP_SCALE`.\n * Used to measure how much the window has converged -- compared against `resetThreshold`\n * to determine whether the price window is tight enough to exit protection mode.\n * @param minPrice The minimum price in the window\n * @param maxPrice The maximum price in the window\n * @return The scaled bound ratio \\(((max - min) * EXP_SCALE) / min\\)\n */\n function _computePriceBoundRatio(uint128 minPrice, uint128 maxPrice) internal pure returns (uint256) {\n uint256 range = uint256(maxPrice) - uint256(minPrice);\n return (range * EXP_SCALE) / uint256(minPrice);\n }\n\n /**\n * @notice Checks if the spot price has deviated beyond the threshold from the window bounds\n * @dev Pump detection: spot > minPrice * (1 + threshold)\n * Crash detection: spot < maxPrice * (1 - threshold)\n * @param spot The current spot price\n * @param minPrice The minimum price in the window\n * @param maxPrice The maximum price in the window\n * @param threshold The deviation threshold (mantissa)\n * @return True if deviation is triggered\n */\n function _exceedsDeviationThreshold(\n uint256 spot,\n uint128 minPrice,\n uint128 maxPrice,\n uint256 threshold\n ) internal pure returns (bool) {\n uint256 upperBound = (uint256(minPrice) * (EXP_SCALE + threshold)) / EXP_SCALE;\n uint256 lowerBound = (uint256(maxPrice) * (EXP_SCALE - threshold)) / EXP_SCALE;\n return (spot > upperBound || spot < lowerBound);\n }\n\n /**\n * @dev Returns true if the relative drift between onChain and proposed exceeds KEEPER_DEADBAND\n * @param currentPrice The current on-chain price\n * @param proposedPrice The keeper's proposed price\n * @return True if drift exceeds deadband\n */\n function _exceedsCorrectionDeadband(uint128 currentPrice, uint128 proposedPrice) internal pure returns (bool) {\n if (currentPrice == 0 || proposedPrice == 0) return false;\n uint256 diff = currentPrice > proposedPrice\n ? uint256(currentPrice - proposedPrice)\n : uint256(proposedPrice - currentPrice);\n return (diff * EXP_SCALE) / uint256(currentPrice) > KEEPER_DEADBAND;\n }\n\n /**\n * @dev Sets the minimum price in the window and emits MinPriceUpdated\n * @param state The market protection state\n * @param asset The underlying asset address (for event emission)\n * @param newMin The new minimum price\n */\n function _setMinPrice(MarketProtectionState storage state, address asset, uint128 newMin) internal {\n emit MinPriceUpdated(asset, state.minPrice, newMin);\n state.minPrice = newMin;\n }\n\n /**\n * @dev Sets the maximum price in the window and emits MaxPriceUpdated\n * @param state The market protection state\n * @param asset The underlying asset address (for event emission)\n * @param newMax The new maximum price\n */\n function _setMaxPrice(MarketProtectionState storage state, address asset, uint128 newMax) internal {\n emit MaxPriceUpdated(asset, state.maxPrice, newMax);\n state.maxPrice = newMax;\n }\n\n /**\n * @dev Writes both lower and upper bounded prices to transient storage\n * @param asset The underlying asset address\n * @param minPrice The resolved lower (collateral) price to cache\n * @param maxPrice The resolved upper (debt) price to cache\n */\n function _setCachedPrices(address asset, uint256 minPrice, uint256 maxPrice) internal {\n Transient.cachePrice(COLLATERAL_PRICE_CACHE_SLOT, asset, minPrice);\n Transient.cachePrice(DEBT_PRICE_CACHE_SLOT, asset, maxPrice);\n }\n\n /**\n * @dev Reads a cached final price from transient storage\n * @param asset The underlying asset address\n * @return minPrice The cached minimum price, or 0 on cache miss\n * @return maxPrice The cached maximum price, or 0 on cache miss\n */\n function _getCachedPrices(address asset) internal view returns (uint256 minPrice, uint256 maxPrice) {\n minPrice = Transient.readCachedPrice(COLLATERAL_PRICE_CACHE_SLOT, asset);\n maxPrice = Transient.readCachedPrice(DEBT_PRICE_CACHE_SLOT, asset);\n }\n\n /**\n * @dev This function returns the underlying asset of a vToken\n * @param vToken vToken address\n * @return asset underlying asset address\n */\n function _getUnderlyingAsset(address vToken) private view returns (address asset) {\n ensureNonzeroAddress(vToken);\n if (vToken == nativeMarket) {\n asset = NATIVE_TOKEN_ADDR;\n } else if (vToken == vai) {\n asset = vai;\n } else {\n asset = VBep20Interface(vToken).underlying();\n }\n }\n\n /**\n * @dev Reverts if the market has not been initialized via setTokenConfig\n * @param asset The underlying asset address\n * @return state The market protection state storage pointer\n */\n function _ensureInitialized(address asset) internal view returns (MarketProtectionState storage state) {\n state = assetProtectionConfig[asset];\n if (state.asset == address(0)) revert MarketNotInitialized(asset);\n }\n\n /**\n * @notice Fetches the current spot price for an asset from the ResilientOracle\n * @param asset The underlying asset address\n * @return The current spot price\n */\n function _fetchSpotPrice(address asset) internal view returns (uint256) {\n return RESILIENT_ORACLE.getPrice(asset);\n }\n\n /**\n * @dev Safely casts a uint256 to uint128, reverting on overflow\n * @param value The value to cast\n * @return The value as uint128\n */\n function _safeToUint128(uint256 value) internal pure returns (uint128) {\n if (value > type(uint128).max) revert PriceExceedsUint128(value);\n return uint128(value);\n }\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ninterface IDeviationBoundedOracle {\n // --- Enums ---\n\n /// @notice Identifies whether a price bound is a minimum or maximum\n enum PriceBoundType {\n MIN,\n MAX\n }\n\n // --- Structs ---\n\n /// @notice Per-asset protection state tracking the min/max price window\n struct MarketProtectionState {\n /// @notice Lowest price observed in the current window (packed with maxPrice in one slot)\n uint128 minPrice;\n /// @notice Highest price observed in the current window\n uint128 maxPrice;\n /// @notice Whether protected price is currently being used\n bool currentlyUsingProtectedPrice;\n /// @notice Whether this market is whitelisted for bounded pricing\n bool isBoundedPricingEnabled;\n /// @notice Timestamp of the last protection trigger — reset on every trigger\n uint64 lastProtectionTriggeredAt;\n /// @notice Minimum time protection stays active after last trigger\n uint64 cooldownPeriod;\n /// @notice The underlying asset address, used to verify initialization\n address asset;\n /// @notice Entry deviation threshold (mantissa, e.g. 0.1667e18 = 16.67%); packed with resetThreshold\n uint128 triggerThreshold;\n /// @notice Exit threshold (mantissa); window must converge below this for protection to be disabled\n uint128 resetThreshold;\n }\n\n // --- Events ---\n\n /// @notice Emitted when protection is initialized for an asset\n event ProtectionInitialized(\n address indexed asset,\n uint128 minPrice,\n uint128 maxPrice,\n uint64 cooldownPeriod,\n uint256 triggerThreshold\n );\n\n /// @notice Emitted when protection mode is triggered for an asset\n event ProtectionTriggered(address indexed asset, uint256 spotPrice, uint128 minPrice, uint128 maxPrice);\n\n /// @notice Emitted when protection mode is disabled for an asset\n event ProtectionModeExited(address indexed asset);\n\n /// @notice Emitted when the keeper updates the minimum price for an asset\n event MinPriceUpdated(address indexed asset, uint128 oldMin, uint128 newMin);\n\n /// @notice Emitted when the keeper updates the maximum price for an asset\n event MaxPriceUpdated(address indexed asset, uint128 oldMax, uint128 newMax);\n\n /// @notice Emitted when the entry threshold is updated for an asset\n event TriggerThresholdSet(address indexed asset, uint256 oldThreshold, uint256 newThreshold);\n\n /// @notice Emitted when the exit threshold is updated for an asset\n event ResetThresholdSet(address indexed asset, uint256 oldExitThreshold, uint256 newExitThreshold);\n\n /// @notice Emitted when the cooldown period is updated for an asset\n event CooldownPeriodSet(address indexed asset, uint64 oldCooldown, uint64 newCooldown);\n\n /// @notice Emitted when an asset's whitelist status changes\n event BoundedPricingWhitelistUpdated(address indexed asset, bool whitelisted);\n\n // --- Errors ---\n\n /// @notice Thrown when trying to initialize protection for an asset that is not initialized\n error MarketNotInitialized(address asset);\n\n /// @notice Thrown when trying to initialize an already initialized market\n error MarketAlreadyInitialized(address asset);\n\n /// @notice Thrown when trying to disable protection that is not active\n error ProtectedPriceInactive(address asset);\n\n /// @notice Thrown when trying to disable protection before cooldown has elapsed\n error CooldownNotElapsed(address asset, uint64 lastProtectionTriggeredAt, uint64 cooldownPeriod);\n\n /// @notice Thrown when trying to disable protection before price range has converged\n error PriceRangeNotConverged(address asset, uint256 currentRangeRatio, uint256 resetThreshold);\n\n /// @notice Thrown when keeper tries to set minPrice above current spot\n error InvalidMinPrice(address asset, uint128 newMin, uint256 currentSpot);\n\n /// @notice Thrown when keeper tries to set maxPrice below current spot\n error InvalidMaxPrice(address asset, uint128 newMax, uint256 currentSpot);\n\n /// @notice Thrown when threshold is set below the minimum allowed value\n error ThresholdBelowMinimum(uint256 threshold, uint256 minimum);\n\n /// @notice Thrown when threshold is set above the maximum allowed value\n error ThresholdAboveMaximum(uint256 threshold, uint256 maximum);\n\n /// @notice Thrown when a price exceeds uint128 max\n error PriceExceedsUint128(uint256 price);\n\n /// @notice Thrown when a zero price is provided where a non-zero price is required\n error ZeroPriceNotAllowed();\n\n /// @notice Thrown when trying to initialize protection for VAI\n error VAINotAllowed();\n\n /// @notice Thrown when trying to update for an asset with active protection\n error ProtectedPriceActive(address asset);\n\n /// @notice Thrown when the lengths of the arrays are not equal\n error InvalidArrayLength();\n\n /// @notice Thrown when the exit threshold is set above the deviation threshold\n error InvalidResetThreshold(uint256 resetThreshold);\n\n // --- Non-view price functions (update window + trigger protection) ---\n\n /**\n * @notice Gets the bounded collateral price for a given vToken, updating protection state\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedCollateralPrice(address vToken) external returns (uint256 collateralPrice);\n\n /**\n * @notice Gets the bounded debt price for a given vToken, updating protection state\n * @param vToken vToken address\n * @return debtPrice The bounded debt price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedDebtPrice(address vToken) external returns (uint256 debtPrice);\n\n /**\n * @notice Gets both the bounded collateral and debt prices for a given vToken, updating protection state\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @return debtPrice The bounded debt price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function getBoundedPrices(address vToken) external returns (uint256 collateralPrice, uint256 debtPrice);\n\n // --- State update (call before view price reads to populate transient cache) ---\n\n /**\n * @notice Updates the protection state for a given vToken, caching the resolved price\n * @dev Called by PolicyFacet before liquidity calculations so subsequent view price\n * reads in the same transaction are served from transient storage.\n * @param vToken vToken address\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event MinPriceUpdated if a new window minimum is recorded\n * @custom:event MaxPriceUpdated if a new window maximum is recorded\n * @custom:event ProtectionTriggered if the spot price deviates beyond the threshold\n */\n function updateProtectionState(address vToken) external;\n\n // --- View price functions (read stored/cached state only) ---\n\n /**\n * @notice Gets the bounded collateral price for a given vToken (view variant)\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\n * @param vToken vToken address\n * @return price The bounded collateral price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\n */\n function getBoundedCollateralPriceView(address vToken) external view returns (uint256 price);\n\n /**\n * @notice Gets the bounded debt price for a given vToken (view variant)\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\n * @param vToken vToken address\n * @return price The bounded debt price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\n */\n function getBoundedDebtPriceView(address vToken) external view returns (uint256 price);\n\n /**\n * @notice Gets both the bounded collateral and debt prices for a given vToken (view variant)\n * @dev Reads from transient cache first; falls back to ResilientOracle on cache miss.\n * @param vToken vToken address\n * @return collateralPrice The bounded collateral price\n * @return debtPrice The bounded debt price\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128 (cache miss path only)\n */\n function getBoundedPricesView(address vToken) external view returns (uint256 collateralPrice, uint256 debtPrice);\n\n // --- Keeper functions ---\n\n /**\n * @notice Updates the minimum price in the rolling window for a given asset\n * @param asset The underlying asset address\n * @param newMin The new minimum price; must be at or below the current spot and below maxPrice\n * @custom:access Only authorized keeper addresses\n * @custom:error ZeroPriceNotAllowed if newMin is zero\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error InvalidMinPrice if newMin exceeds the current spot or is at or above maxPrice\n * @custom:event MinPriceUpdated\n */\n function updateMinPrice(address asset, uint128 newMin) external;\n\n /**\n * @notice Updates the maximum price in the rolling window for a given asset\n * @param asset The underlying asset address\n * @param newMax The new maximum price; must be at or above the current spot and above minPrice\n * @custom:access Only authorized keeper addresses\n * @custom:error ZeroPriceNotAllowed if newMax is zero\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error InvalidMaxPrice if newMax is below the current spot or is at or below minPrice\n * @custom:event MaxPriceUpdated\n */\n function updateMaxPrice(address asset, uint128 newMax) external;\n\n /**\n * @notice Exits protection mode for a given asset once conditions are met\n * @param asset The underlying asset address\n * @custom:access Only authorized monitor/keeper addresses\n * @custom:error ProtectedPriceInactive if protection is not currently active\n * @custom:error CooldownNotElapsed if the cooldown period has not elapsed since the last trigger\n * @custom:error PriceRangeNotConverged if the window range is still above the exit threshold\n * @custom:event ProtectionModeExited\n */\n function exitProtectionMode(address asset) external;\n\n // --- Admin functions (governance-gated) ---\n\n /**\n * @notice Initializes protection parameters for a new asset\n * @dev Seeds the initial min/max window from the current ResilientOracle spot price,\n * confirming the oracle is live for this asset before it is listed.\n * @param asset The underlying asset address\n * @param cooldownPeriod Minimum time protection stays active after the last trigger, in seconds\n * @param triggerThreshold Deviation threshold that activates protection (mantissa). Must be between 5% and 50%.\n * @param resetThreshold Deviation threshold below which protection can be exited (mantissa). Must be non-zero and below triggerThreshold.\n * @param enableBoundedPricing Whether to enable bounded pricing immediately upon initialization\n * @custom:access Only Governance\n * @custom:error MarketAlreadyInitialized if the asset has already been initialized\n * @custom:error ThresholdBelowMinimum if triggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if triggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if resetThreshold is at or above triggerThreshold\n * @custom:error VAINotAllowed if asset is the VAI token\n * @custom:error PriceExceedsUint128 if the spot price overflows uint128\n * @custom:event ProtectionInitialized\n * @custom:event BoundedPricingWhitelistUpdated\n */\n function setTokenConfig(\n address asset,\n uint64 cooldownPeriod,\n uint256 triggerThreshold,\n uint256 resetThreshold,\n bool enableBoundedPricing\n ) external;\n\n /**\n * @notice Batch-initializes protection parameters for multiple assets in a single transaction\n * @param assets Array of underlying asset addresses\n * @param cooldownPeriods Array of cooldown periods (seconds)\n * @param triggerThresholds Array of trigger thresholds (mantissa)\n * @param resetThresholds Array of reset thresholds (mantissa)\n * @param enableBoundedPricings Array of whether to enable bounded pricing per asset\n * @custom:access Only Governance\n * @custom:error InvalidArrayLength if array lengths do not match\n * @custom:event ProtectionInitialized for each asset\n * @custom:event BoundedPricingWhitelistUpdated for each asset\n */\n function setTokenConfigs(\n address[] calldata assets,\n uint64[] calldata cooldownPeriods,\n uint256[] calldata triggerThresholds,\n uint256[] calldata resetThresholds,\n bool[] calldata enableBoundedPricings\n ) external;\n\n /**\n * @notice Sets the cooldown period for an asset\n * @param asset The underlying asset address\n * @param newCooldown The new cooldown period in seconds; must be non-zero\n * @custom:access Only Governance\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:event CooldownPeriodSet\n */\n function setCooldownPeriod(address asset, uint64 newCooldown) external;\n\n /**\n * @notice Sets the trigger and reset thresholds for an asset\n * @param asset The underlying asset address\n * @param newTriggerThreshold The new trigger threshold (mantissa). Must be between 5% and 50% and above the reset threshold.\n * @param newResetThreshold The new reset threshold (mantissa). Must be non-zero and below the trigger threshold.\n * @custom:access Only Governance\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error ThresholdBelowMinimum if newTriggerThreshold is below 5%\n * @custom:error ThresholdAboveMaximum if newTriggerThreshold is above 50%\n * @custom:error InvalidResetThreshold if newResetThreshold is at or above newTriggerThreshold\n * @custom:event TriggerThresholdSet if the trigger threshold changed\n * @custom:event ResetThresholdSet if the reset threshold changed\n */\n function setThresholds(address asset, uint256 newTriggerThreshold, uint256 newResetThreshold) external;\n\n /**\n * @notice Sets whether bounded pricing is enabled for an asset\n * @param asset The underlying asset address\n * @param enabled Whether bounded pricing should be enabled for the asset\n * @custom:access Only Governance\n * @custom:error MarketNotInitialized if the asset has not been initialized\n * @custom:error ProtectedPriceActive if trying to disable an asset while protection is active\n * @custom:event BoundedPricingWhitelistUpdated\n */\n function setAssetBoundedPricingEnabled(address asset, bool enabled) external;\n\n // --- View helpers ---\n\n /**\n * @notice Returns the full protection state for an asset\n * @param asset The underlying asset address\n * @return minPrice Lowest price observed in the current window\n * @return maxPrice Highest price observed in the current window\n * @return currentlyUsingProtectedPrice Whether protected price is currently active\n * @return isBoundedPricingEnabled Whether the asset is whitelisted for bounded pricing\n * @return lastProtectionTriggeredAt Timestamp of the last protection trigger\n * @return cooldownPeriod Minimum time protection stays active after last trigger\n * @return assetAddr The underlying asset address stored in the struct\n * @return triggerThreshold Entry deviation threshold (mantissa) that activates protection\n * @return resetThreshold Exit deviation threshold (mantissa) below which protection can be disabled\n */\n function assetProtectionConfig(\n address asset\n )\n external\n view\n returns (\n uint128 minPrice,\n uint128 maxPrice,\n bool currentlyUsingProtectedPrice,\n bool isBoundedPricingEnabled,\n uint64 lastProtectionTriggeredAt,\n uint64 cooldownPeriod,\n address assetAddr,\n uint128 triggerThreshold,\n uint128 resetThreshold\n );\n\n /**\n * @notice Checks if an asset is whitelisted for bounded pricing\n * @param asset The underlying asset address\n * @return True if the asset is whitelisted\n */\n function isBoundedPricingEnabled(address asset) external view returns (bool);\n\n /**\n * @notice Checks if the asset is currently using the protected (bounded) price\n * @param asset The underlying asset address\n * @return True if the asset is currently using the protected price instead of spot\n */\n function currentlyUsingProtectedPrice(address asset) external view returns (bool);\n\n /**\n * @notice Checks if protection can be exited for a given asset\n * @param asset The underlying asset address\n * @return True if both the cooldown has elapsed and the price range has converged below the exit threshold\n */\n function canExitProtection(address asset) external view returns (bool);\n\n /**\n * @notice Returns the initialized asset at the given index (auto-generated array getter)\n * @param index Array index\n * @return The asset address at the given index\n */\n function allAssets(uint256 index) external view returns (address);\n\n /**\n * @notice Returns all currently whitelisted asset addresses\n * @return result Array of whitelisted asset addresses\n */\n function getAllBoundedPricingEnabledAssets() external view returns (address[] memory result);\n\n /**\n * @notice Returns all asset addresses that have ever been initialized\n * @return Array of all initialized asset addresses\n */\n function getInitializedAssets() external view returns (address[] memory);\n\n /**\n * @notice Batch-checks which assets' on-chain min/max have drifted beyond the keeper deadband\n * @param assets Array of asset addresses to check\n * @param proposedMins Keeper's proposed window minimum prices\n * @param proposedMaxs Keeper's proposed window maximum prices\n * @return needsMinUpdate Whether minPrice drift exceeds the deadband for each asset\n * @return needsMaxUpdate Whether maxPrice drift exceeds the deadband for each asset\n * @custom:error InvalidArrayLength if the input array lengths do not match\n */\n function checkAndGetWindowDrift(\n address[] calldata assets,\n uint128[] calldata proposedMins,\n uint128[] calldata proposedMaxs\n ) external view returns (bool[] memory needsMinUpdate, bool[] memory needsMaxUpdate);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface OracleInterface {\n function getPrice(address asset) external view returns (uint256);\n}\n\ninterface ResilientOracleInterface is OracleInterface {\n function updatePrice(address vToken) external;\n\n function updateAssetPrice(address asset) external;\n\n function getUnderlyingPrice(address vToken) external view returns (uint256);\n}\n\ninterface BoundValidatorInterface {\n function validatePriceWithAnchorPrice(\n address asset,\n uint256 reporterPrice,\n uint256 anchorPrice\n ) external view returns (bool);\n}\n" + }, + "@venusprotocol/oracle/contracts/interfaces/VBep20Interface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface VBep20Interface is IERC20Metadata {\n /**\n * @notice Underlying asset for this VToken\n */\n function underlying() external view returns (address);\n}\n" + }, + "@venusprotocol/oracle/contracts/lib/Transient.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nlibrary Transient {\n /**\n * @notice Cache the asset price into transient storage\n * @param key address of the asset\n * @param value asset price\n */\n function cachePrice(bytes32 cacheSlot, address key, uint256 value) internal {\n bytes32 slot = keccak256(abi.encode(cacheSlot, key));\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @notice Read cached price from transient storage\n * @param key address of the asset\n * @return value cached asset price\n */\n function readCachedPrice(bytes32 cacheSlot, address key) internal view returns (uint256 value) {\n bytes32 slot = keccak256(abi.encode(cacheSlot, key));\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/constants.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/// @dev Base unit for computations, usually used in scaling (multiplications, divisions)\nuint256 constant EXP_SCALE = 1e18;\n\n/// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\nuint256 constant MANTISSA_ONE = EXP_SCALE;\n\n/// @dev The approximate number of seconds per year\nuint256 constant SECONDS_PER_YEAR = 31_536_000;\n" + }, + "@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title MaxLoopsLimitHelper\n * @author Venus\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\n */\nabstract contract MaxLoopsLimitHelper {\n // Limit for the loops to avoid the DOS\n uint256 public maxLoopsLimit;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when max loops limit is set\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\n\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function _setMaxLoopsLimit(uint256 limit) internal {\n require(limit > maxLoopsLimit, \"Comptroller: Invalid maxLoopsLimit\");\n\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\n maxLoopsLimit = limit;\n\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\n }\n\n /**\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\n * @param len Length of the loops iterate\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\n */\n function _ensureMaxLoops(uint256 len) internal view {\n if (len > maxLoopsLimit) {\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\n }\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { SECONDS_PER_YEAR } from \"./constants.sol\";\n\nabstract contract TimeManagerV8 {\n /// @notice Stores blocksPerYear if isTimeBased is true else secondsPerYear is stored\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable blocksOrSecondsPerYear;\n\n /// @notice Acknowledges if a contract is time based or not\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n bool public immutable isTimeBased;\n\n /// @notice Stores the current block timestamp or block number depending on isTimeBased\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n function() view returns (uint256) private immutable _getCurrentSlot;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[48] private __gap;\n\n /// @notice Thrown when blocks per year is invalid\n error InvalidBlocksPerYear();\n\n /// @notice Thrown when time based but blocks per year is provided\n error InvalidTimeBasedConfiguration();\n\n /**\n * @param timeBased_ A boolean indicating whether the contract is based on time or block\n * If timeBased is true than blocksPerYear_ param is ignored as blocksOrSecondsPerYear is set to SECONDS_PER_YEAR\n * @param blocksPerYear_ The number of blocks per year\n * @custom:error InvalidBlocksPerYear is thrown if blocksPerYear entered is zero and timeBased is false\n * @custom:error InvalidTimeBasedConfiguration is thrown if blocksPerYear entered is non zero and timeBased is true\n * @custom:oz-upgrades-unsafe-allow constructor\n */\n constructor(bool timeBased_, uint256 blocksPerYear_) {\n if (!timeBased_ && blocksPerYear_ == 0) {\n revert InvalidBlocksPerYear();\n }\n\n if (timeBased_ && blocksPerYear_ != 0) {\n revert InvalidTimeBasedConfiguration();\n }\n\n isTimeBased = timeBased_;\n blocksOrSecondsPerYear = timeBased_ ? SECONDS_PER_YEAR : blocksPerYear_;\n _getCurrentSlot = timeBased_ ? _getBlockTimestamp : _getBlockNumber;\n }\n\n /**\n * @dev Function to simply retrieve block number or block timestamp\n * @return Current block number or block timestamp\n */\n function getBlockNumberOrTimestamp() public view virtual returns (uint256) {\n return _getCurrentSlot();\n }\n\n /**\n * @dev Returns the current timestamp in seconds\n * @return The current timestamp\n */\n function _getBlockTimestamp() private view returns (uint256) {\n return block.timestamp;\n }\n\n /**\n * @dev Returns the current block number\n * @return The current block number\n */\n function _getBlockNumber() private view returns (uint256) {\n return block.number;\n }\n}\n" + }, + "@venusprotocol/solidity-utilities/contracts/validators.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/// @notice Thrown if the supplied address is a zero address where it is not allowed\nerror ZeroAddressNotAllowed();\n\n/// @notice Thrown if the supplied value is 0 where it is not allowed\nerror ZeroValueNotAllowed();\n\n/// @notice Checks if the provided address is nonzero, reverts otherwise\n/// @param address_ Address to check\n/// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\nfunction ensureNonzeroAddress(address address_) pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n}\n\n/// @notice Checks if the provided value is nonzero, reverts otherwise\n/// @param value_ Value to check\n/// @custom:error ZeroValueNotAllowed is thrown if the provided value is 0\nfunction ensureNonzeroValue(uint256 value_) pure {\n if (value_ == 0) {\n revert ZeroValueNotAllowed();\n }\n}\n" + }, + "contracts/Admin/VBNBAdmin.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IProtocolShareReserve } from \"../external/IProtocolShareReserve.sol\";\nimport { IWBNB } from \"../external/IWBNB.sol\";\nimport { VBNBAdminStorage, VTokenInterface } from \"./VBNBAdminStorage.sol\";\n\n/**\n * @title VBNBAdmin\n * @author Venus\n * @notice This contract is the \"admin\" of the vBNB market, reducing the reserves of the market, sending them to the `ProtocolShareReserve` contract,\n * and allowing the executions of the rest of the privileged functions in the vBNB contract (after checking if the sender has the required permissions).\n */\ncontract VBNBAdmin is ReentrancyGuardUpgradeable, AccessControlledV8, VBNBAdminStorage {\n using SafeERC20Upgradeable for IWBNB;\n\n /// @notice address of vBNB\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n VTokenInterface public immutable vBNB;\n\n /// @notice address of WBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IWBNB public immutable WBNB;\n\n /// @notice Emitted when PSR is updated\n event ProtocolShareReserveUpdated(\n IProtocolShareReserve indexed oldProtocolShareReserve,\n IProtocolShareReserve indexed newProtocolShareReserve\n );\n\n /// @notice Emitted reserves are reduced\n event ReservesReduced(uint256 reduceAmount);\n\n /// @param _vBNB Address of the vBNB contract\n /// @param _WBNB Address of the WBNB token\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(VTokenInterface _vBNB, IWBNB _WBNB) {\n require(address(_WBNB) != address(0), \"WBNB address invalid\");\n require(address(_vBNB) != address(0), \"vBNB address invalid\");\n\n vBNB = _vBNB;\n WBNB = _WBNB;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /// @notice Used to initialize non-immutable variables\n function initialize(\n IProtocolShareReserve _protocolShareReserve,\n address accessControlManager\n ) external initializer {\n require(address(_protocolShareReserve) != address(0), \"PSR address invalid\");\n protocolShareReserve = _protocolShareReserve;\n\n __ReentrancyGuard_init();\n __AccessControlled_init(accessControlManager);\n }\n\n /**\n * @notice PSR setter.\n * @param protocolShareReserve_ Address of the PSR contract\n * @custom:access Only owner (Governance)\n * @custom:event Emits ProtocolShareReserveUpdated event.\n */\n function setProtocolShareReserve(IProtocolShareReserve protocolShareReserve_) external onlyOwner {\n require(address(protocolShareReserve_) != address(0), \"PSR address invalid\");\n emit ProtocolShareReserveUpdated(protocolShareReserve, protocolShareReserve_);\n protocolShareReserve = protocolShareReserve_;\n }\n\n /**\n * @notice Reduce reserves of vBNB, wrap them and send them to the PSR contract\n * @param reduceAmount amount of reserves to reduce\n * @custom:event Emits ReservesReduced event.\n */\n function reduceReserves(uint reduceAmount) external nonReentrant {\n require(vBNB._reduceReserves(reduceAmount) == 0, \"reduceReserves failed\");\n _wrapBNB();\n\n uint256 balance = WBNB.balanceOf(address(this));\n WBNB.safeTransfer(address(protocolShareReserve), balance);\n protocolShareReserve.updateAssetsState(\n vBNB.comptroller(),\n address(WBNB),\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit ReservesReduced(reduceAmount);\n }\n\n /**\n * @notice Sets the interest rate model of the vBNB contract\n * @param newInterestRateModel Address of the new interest rate model\n * @custom:access Controlled by ACM\n */\n function setInterestRateModel(address newInterestRateModel) public returns (uint256) {\n _checkAccessAllowed(\"setInterestRateModel(address)\");\n return vBNB._setInterestRateModel(newInterestRateModel);\n }\n\n /**\n * @notice Wraps BNB into WBNB\n */\n function _wrapBNB() internal {\n uint256 bnbBalance = address(this).balance;\n WBNB.deposit{ value: bnbBalance }();\n }\n\n /**\n * @notice Invoked when BNB is sent to this contract\n * @custom:access Only vBNB is considered a valid sender\n */\n receive() external payable {\n require(msg.sender == address(vBNB), \"only vBNB can send BNB to this contract\");\n }\n\n /**\n * @notice Invoked when called function does not exist in the contract. The function will be executed in the vBNB contract.\n * @custom:access Only owner (Governance)\n */\n fallback(bytes calldata data) external payable onlyOwner returns (bytes memory) {\n (bool ok, bytes memory res) = address(vBNB).call{ value: msg.value }(data);\n require(ok, \"call failed\");\n return res;\n }\n}\n" + }, + "contracts/Admin/VBNBAdminStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IProtocolShareReserve } from \"../external/IProtocolShareReserve.sol\";\n\ninterface VTokenInterface {\n function _reduceReserves(uint reduceAmount) external returns (uint);\n\n function _acceptAdmin() external returns (uint);\n\n function comptroller() external returns (address);\n\n function _setInterestRateModel(address newInterestRateModel) external returns (uint);\n}\n\ncontract VBNBAdminStorage {\n /// @notice address of protocol share reserve contract\n IProtocolShareReserve public protocolShareReserve;\n\n /// @dev gap to prevent collision in inheritence\n uint256[49] private __gap;\n}\n" + }, + "contracts/Comptroller/ComptrollerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { VAIControllerInterface } from \"../Tokens/VAI/VAIControllerInterface.sol\";\nimport { WeightFunction } from \"./Diamond/interfaces/IFacetBase.sol\";\n\nenum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n}\n\ninterface ComptrollerInterface {\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() external pure returns (bool);\n\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\n\n function exitMarket(address vToken) external returns (uint);\n\n /*** Policy Hooks ***/\n\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function executeFlashLoan(\n address payable onBehalf,\n address payable receiver,\n VToken[] calldata vTokens,\n uint256[] calldata underlyingAmounts,\n bytes calldata param\n ) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external returns (uint);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function liquidateCalculateSeizeTokens(\n address borrower,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function getXVSAddress() external view returns (address);\n\n function markets(address) external view returns (bool, uint, bool, uint, uint, uint96, bool);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function deviationBoundedOracle() external view returns (IDeviationBoundedOracle);\n\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function claimVenus(address) external;\n\n function venusAccrued(address) external view returns (uint);\n\n function venusSupplySpeeds(address) external view returns (uint);\n\n function venusBorrowSpeeds(address) external view returns (uint);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function venusSupplierIndex(address, address) external view returns (uint);\n\n function venusInitialIndex() external view returns (uint224);\n\n function venusBorrowerIndex(address, address) external view returns (uint);\n\n function venusBorrowState(address) external view returns (uint224, uint32);\n\n function venusSupplyState(address) external view returns (uint224, uint32);\n\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\n\n function vaiController() external view returns (VAIControllerInterface);\n\n function protocolPaused() external view returns (bool);\n\n function actionPaused(address market, Action action) external view returns (bool);\n\n function mintedVAIs(address user) external view returns (uint);\n\n function vaiMintRate() external view returns (uint);\n\n function authorizedFlashLoan(address account) external view returns (bool);\n\n function userPoolId(address account) external view returns (uint96);\n\n function getLiquidationIncentive(address vToken) external view returns (uint256);\n\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\n\n function getEffectiveLtvFactor(\n address account,\n address vToken,\n WeightFunction weightingStrategy\n ) external view returns (uint256);\n\n function lastPoolId() external view returns (uint96);\n\n function corePoolId() external pure returns (uint96);\n\n function pools(\n uint96 poolId\n ) external view returns (string memory label, bool isActive, bool allowCorePoolFallback);\n\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\n\n function poolMarkets(\n uint96 poolId,\n address vToken\n )\n external\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n );\n\n function isFlashLoanPaused() external view returns (bool);\n}\n\ninterface IVAIVault {\n function updatePendingRewards() external;\n}\n\ninterface IComptroller {\n /*** Treasury Data ***/\n function treasuryAddress() external view returns (address);\n\n function treasuryPercent() external view returns (uint);\n}\n" + }, + "contracts/Comptroller/ComptrollerLensInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { WeightFunction } from \"./Diamond/interfaces/IFacetBase.sol\";\n\ninterface ComptrollerLensInterface {\n function liquidateCalculateSeizeTokens(\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function liquidateCalculateSeizeTokens(\n address borrower,\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function liquidateVAICalculateSeizeTokens(\n address comptroller,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function getHypotheticalAccountLiquidity(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount,\n WeightFunction weightingStrategy\n ) external view returns (uint, uint, uint);\n}\n" + }, + "contracts/Comptroller/ComptrollerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\nimport { PoolMarketId } from \"./Types/PoolMarketId.sol\";\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { VAIControllerInterface } from \"../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterface } from \"./ComptrollerLensInterface.sol\";\nimport { IPrime } from \"../Tokens/Prime/IPrime.sol\";\n\ncontract UnitrollerAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of Unitroller\n */\n address public comptrollerImplementation;\n\n /**\n * @notice Pending brains of Unitroller\n */\n address public pendingComptrollerImplementation;\n}\n\ncontract ComptrollerV1Storage is UnitrollerAdminStorage {\n /**\n * @notice Oracle which gives the price of any given asset\n */\n ResilientOracleInterface public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives (deprecated)\n */\n uint256 private _oldLiquidationIncentiveMantissa;\n\n /**\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\n */\n uint256 public maxAssets;\n\n /**\n * @notice Per-account mapping of \"assets you are in\", capped by maxAssets\n */\n mapping(address => VToken[]) public accountAssets;\n\n struct Market {\n /// @notice Whether or not this market is listed\n bool isListed;\n /**\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\n * For instance, 0.9 to allow borrowing 90% of collateral value.\n * Must be between 0 and 1, and stored as a mantissa.\n */\n uint256 collateralFactorMantissa;\n /// @notice Per-market mapping of \"accounts in this asset\" (used for Core Pool only)\n mapping(address => bool) accountMembership;\n /// @notice Whether or not this market receives XVS\n bool isVenus;\n /**\n * @notice Multiplier representing the collateralization after which the borrow is eligible\n * for liquidation. For instance, 0.8 liquidate when the borrow is 80% of collateral\n * value. Must be between 0 and collateral factor, stored as a mantissa.\n */\n uint256 liquidationThresholdMantissa;\n /// @notice discount on collateral that a liquidator receives when liquidating a borrow in this market\n uint256 liquidationIncentiveMantissa;\n /// @notice The pool ID this market is associated with, Used to support pools/emodes\n uint96 poolId;\n /// @notice Flag to restrict borrowing in certain pools/emodes.\n bool isBorrowAllowed;\n }\n\n /**\n * @notice Mapping of PoolMarketId -> Market metadata\n * Underlying key layout: First 12 bytes (96 bits) represent the poolId, last 20 bytes the vToken address\n */\n mapping(PoolMarketId => Market) internal _poolMarkets;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n address public pauseGuardian;\n\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\n bool private _mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool private _borrowGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal transferGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal seizeGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal borrowGuardianPaused;\n\n struct VenusMarketState {\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\n uint224 index;\n /// @notice The block number the index was last updated at\n uint32 block;\n }\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice The rate at which the flywheel distributes XVS, per block\n uint256 internal venusRate;\n\n /// @notice The portion of venusRate that each market currently receives\n mapping(address => uint256) internal venusSpeeds;\n\n /// @notice The Venus market supply state for each market\n mapping(address => VenusMarketState) public venusSupplyState;\n\n /// @notice The Venus market borrow state for each market\n mapping(address => VenusMarketState) public venusBorrowState;\n\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\n\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\n\n /// @notice The XVS accrued but not yet transferred to each user\n mapping(address => uint256) public venusAccrued;\n\n /// @notice The Address of VAIController\n VAIControllerInterface public vaiController;\n\n /// @notice The minted VAI amount to each user\n mapping(address => uint256) public mintedVAIs;\n\n /// @notice VAI Mint Rate as a percentage\n uint256 public vaiMintRate;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n bool public mintVAIGuardianPaused;\n bool public repayVAIGuardianPaused;\n\n /**\n * @notice Pause/Unpause whole protocol actions\n */\n bool public protocolPaused;\n\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\n uint256 private venusVAIRate;\n}\n\ncontract ComptrollerV2Storage is ComptrollerV1Storage {\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\n uint256 public venusVAIVaultRate;\n\n // address of VAI Vault\n address public vaiVaultAddress;\n\n // start block of release to VAI Vault\n uint256 public releaseStartBlock;\n\n // minimum release amount to VAI Vault\n uint256 public minReleaseAmount;\n}\n\ncontract ComptrollerV3Storage is ComptrollerV2Storage {\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\n address public borrowCapGuardian;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\n mapping(address => uint256) public borrowCaps;\n}\n\ncontract ComptrollerV4Storage is ComptrollerV3Storage {\n /// @notice Treasury Guardian address\n address public treasuryGuardian;\n\n /// @notice Treasury address\n address public treasuryAddress;\n\n /// @notice Fee percent of accrued interest with decimal 18\n uint256 public treasuryPercent;\n}\n\ncontract ComptrollerV5Storage is ComptrollerV4Storage {\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\n mapping(address => uint256) private venusContributorSpeeds;\n\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\n mapping(address => uint256) private lastContributorBlock;\n}\n\ncontract ComptrollerV6Storage is ComptrollerV5Storage {\n address public liquidatorContract;\n}\n\ncontract ComptrollerV7Storage is ComptrollerV6Storage {\n ComptrollerLensInterface public comptrollerLens;\n}\n\ncontract ComptrollerV8Storage is ComptrollerV7Storage {\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\n mapping(address => uint256) public supplyCaps;\n}\n\ncontract ComptrollerV9Storage is ComptrollerV8Storage {\n /// @notice AccessControlManager address\n address internal accessControl;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\n}\n\ncontract ComptrollerV10Storage is ComptrollerV9Storage {\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public venusBorrowSpeeds;\n\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public venusSupplySpeeds;\n}\n\ncontract ComptrollerV11Storage is ComptrollerV10Storage {\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\n mapping(address => mapping(address => bool)) public approvedDelegates;\n}\n\ncontract ComptrollerV12Storage is ComptrollerV11Storage {\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\n mapping(address => bool) public isForcedLiquidationEnabled;\n}\n\ncontract ComptrollerV13Storage is ComptrollerV12Storage {\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\n }\n\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\n // facet addresses\n address[] internal _facetAddresses;\n}\n\ncontract ComptrollerV14Storage is ComptrollerV13Storage {\n /// @notice Prime token address\n IPrime public prime;\n}\n\ncontract ComptrollerV15Storage is ComptrollerV14Storage {\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\n}\n\ncontract ComptrollerV16Storage is ComptrollerV15Storage {\n /// @notice The XVS token contract address\n address internal xvs;\n\n /// @notice The XVS vToken contract address\n address internal xvsVToken;\n}\n\ncontract ComptrollerV17Storage is ComptrollerV16Storage {\n struct PoolData {\n /// @notice label for the pool\n string label;\n /// @notice List of vToken addresses associated with this pool\n address[] vTokens;\n /**\n * @notice Whether the pool is active and can be entered. If set to false,\n * new entries are disabled and existing accounts fall back to core pool values\n */\n bool isActive;\n /**\n * @notice Whether core pool risk factors can be used as fallback when the market\n * is not configured in the specific pool, falls back when set to true\n */\n bool allowCorePoolFallback;\n }\n\n /**\n * @notice Tracks the selected pool for each user\n * @dev\n * - The mapping stores the pool ID (`uint96`) that each user (`address`) is currently in\n * - A value of `0` represents the default core pool (legacy behavior)\n */\n mapping(address => uint96) public userPoolId;\n\n /**\n * @notice Mapping of pool ID to its corresponding metadata and configuration\n * @dev Pool IDs are unique and incremented via `lastPoolId` when a new pool is created\n * Not updated for the Core Pool (`poolId = 0`)\n */\n mapping(uint96 => PoolData) public pools;\n\n /**\n * @notice Counter used to generate unique pool IDs\n * @dev Increments each time a pool is created; `poolId = 0` is reserved for the core pool\n */\n uint96 public lastPoolId;\n}\n\ncontract ComptrollerV18Storage is ComptrollerV17Storage {\n /// @notice Mapping of accounts authorized to execute flash loans\n mapping(address => bool) public authorizedFlashLoan;\n\n /// @notice Whether flash loans are paused system-wide\n bool public flashLoanPaused;\n}\n\ncontract ComptrollerV19Storage is ComptrollerV18Storage {\n /// @notice DeviationBoundedOracle for conservative pricing in CF path\n IDeviationBoundedOracle public deviationBoundedOracle;\n}\n" + }, + "contracts/Comptroller/Diamond/Diamond.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IDiamondCut } from \"./interfaces/IDiamondCut.sol\";\nimport { Unitroller } from \"../Unitroller.sol\";\nimport { ComptrollerV19Storage } from \"../ComptrollerStorage.sol\";\n\n/**\n * @title Diamond\n * @author Venus\n * @notice This contract contains functions related to facets\n */\ncontract Diamond is IDiamondCut, ComptrollerV19Storage {\n /// @notice Emitted when functions are added, replaced or removed to facets\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut);\n\n struct Facet {\n address facetAddress;\n bytes4[] functionSelectors;\n }\n\n /**\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\n * @param unitroller Address of the unitroller\n */\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n /**\n * @notice To add function selectors to the facet's mapping\n * @dev Allows the contract admin to add function selectors\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\n */\n function diamondCut(IDiamondCut.FacetCut[] memory diamondCut_) public {\n require(msg.sender == admin, \"only unitroller admin can\");\n libDiamondCut(diamondCut_);\n }\n\n /**\n * @notice Get all function selectors mapped to the facet address\n * @param facet Address of the facet\n * @return selectors Array of function selectors\n */\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\n return _facetFunctionSelectors[facet].functionSelectors;\n }\n\n /**\n * @notice Get facet position in the _facetFunctionSelectors through facet address\n * @param facet Address of the facet\n * @return Position of the facet\n */\n function facetPosition(address facet) external view returns (uint256) {\n return _facetFunctionSelectors[facet].facetAddressPosition;\n }\n\n /**\n * @notice Get all facet addresses\n * @return facetAddresses Array of facet addresses\n */\n function facetAddresses() external view returns (address[] memory) {\n return _facetAddresses;\n }\n\n /**\n * @notice Get facet address and position through function selector\n * @param functionSelector function selector\n * @return FacetAddressAndPosition facet address and position\n */\n function facetAddress(\n bytes4 functionSelector\n ) external view returns (ComptrollerV19Storage.FacetAddressAndPosition memory) {\n return _selectorToFacetAndPosition[functionSelector];\n }\n\n /**\n * @notice Get all facets address and their function selector\n * @return facets_ Array of Facet\n */\n function facets() external view returns (Facet[] memory) {\n uint256 facetsLength = _facetAddresses.length;\n Facet[] memory facets_ = new Facet[](facetsLength);\n for (uint256 i; i < facetsLength; ++i) {\n address facet = _facetAddresses[i];\n facets_[i].facetAddress = facet;\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\n }\n return facets_;\n }\n\n /**\n * @notice To add function selectors to the facets' mapping\n * @param diamondCut_ IDiamondCut contains facets address, action and function selectors\n */\n function libDiamondCut(IDiamondCut.FacetCut[] memory diamondCut_) internal {\n uint256 diamondCutLength = diamondCut_.length;\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\n IDiamondCut.FacetCutAction action = diamondCut_[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n }\n emit DiamondCut(diamondCut_);\n }\n\n /**\n * @notice Add function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to add in the mapping\n */\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress == address(0), \"LibDiamondCut: Can't add function that already exists\");\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to replace in the mapping\n */\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress != facetAddress, \"LibDiamondCut: Can't replace function with same function\");\n removeFunction(oldFacetAddress, selector);\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Remove function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to remove in the mapping\n */\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n uint256 functionSelectorsLength = functionSelectors.length;\n require(functionSelectorsLength != 0, \"LibDiamondCut: No selectors in facet to cut\");\n // if function does not exist then do nothing and revert\n require(facetAddress == address(0), \"LibDiamondCut: Remove facet address must be address(0)\");\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n removeFunction(oldFacetAddress, selector);\n }\n }\n\n /**\n * @notice Add new facet to the proxy\n * @param facetAddress Address of the facet\n */\n function addFacet(address facetAddress) internal {\n enforceHasContractCode(facetAddress, \"Diamond: New facet has no code\");\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\n _facetAddresses.push(facetAddress);\n }\n\n /**\n * @notice Add function selector to the facet's address mapping\n * @param selector funciton selector need to be added\n * @param selectorPosition funciton selector position\n * @param facetAddress Address of the facet\n */\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\n }\n\n /**\n * @notice Remove function selector to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param selector function selectors need to remove in the mapping\n */\n function removeFunction(address facetAddress, bytes4 selector) internal {\n require(facetAddress != address(0), \"LibDiamondCut: Can't remove function that doesn't exist\");\n\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\n // if not the same then replace selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\n delete _selectorToFacetAndPosition[selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\n }\n _facetAddresses.pop();\n delete _facetFunctionSelectors[facetAddress];\n }\n }\n\n /**\n * @dev Ensure that the given address has contract code deployed\n * @param _contract The address to check for contract code\n * @param _errorMessage The error message to display if the contract code is not deployed\n */\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\n uint256 contractSize;\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize != 0, _errorMessage);\n }\n\n // Find facet for function that is called and execute the\n // function if a facet is found and return any value.\n fallback() external {\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\n require(facet != address(0), \"Diamond: Function does not exist\");\n // Execute public function from facet using delegatecall and return any value.\n assembly {\n // copy function selector and any arguments\n calldatacopy(0, 0, calldatasize())\n // execute function call using the facet\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\n // get any return value\n returndatacopy(0, 0, returndatasize())\n // return any return value or error back to the caller\n switch result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/DiamondConsolidated.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { MarketFacet } from \"./facets/MarketFacet.sol\";\nimport { PolicyFacet } from \"./facets/PolicyFacet.sol\";\nimport { RewardFacet } from \"./facets/RewardFacet.sol\";\nimport { SetterFacet } from \"./facets/SetterFacet.sol\";\nimport { FlashLoanFacet } from \"./facets/FlashLoanFacet.sol\";\nimport { Diamond } from \"./Diamond.sol\";\n\n/**\n * @title DiamondConsolidated\n * @author Venus\n * @notice This contract contains the functions defined in the different facets of the Diamond, plus the getters to the public variables.\n * This contract cannot be deployed, due to its size. Its main purpose is to allow the easy generation of an ABI and the typechain to interact with the\n * Unitroller contract in a simple way\n */\ncontract DiamondConsolidated is Diamond, MarketFacet, PolicyFacet, RewardFacet, SetterFacet, FlashLoanFacet {}\n" + }, + "contracts/Comptroller/Diamond/facets/FacetBase.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { ComptrollerErrorReporter } from \"../../../Utils/ErrorReporter.sol\";\nimport { ExponentialNoError } from \"../../../Utils/ExponentialNoError.sol\";\nimport { IVAIVault, Action } from \"../../../Comptroller/ComptrollerInterface.sol\";\nimport { ComptrollerV19Storage } from \"../../../Comptroller/ComptrollerStorage.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\nimport { IFacetBase, WeightFunction } from \"../interfaces/IFacetBase.sol\";\n\n/**\n * @title FacetBase\n * @author Venus\n * @notice This facet contract contains functions related to access and checks\n */\ncontract FacetBase is IFacetBase, ComptrollerV19Storage, ExponentialNoError, ComptrollerErrorReporter {\n using SafeERC20 for IERC20;\n\n /// @notice The initial Venus index for a market\n uint224 public constant venusInitialIndex = 1e36;\n // poolId for core Pool\n uint96 public constant corePoolId = 0;\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\n // closeFactorMantissa must not exceed this value\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when XVS is distributed to VAI Vault\n event DistributedVAIVaultVenus(uint256 amount);\n\n /// @notice Reverts if the protocol is paused\n function checkProtocolPauseState() internal view {\n require(!protocolPaused, \"protocol is paused\");\n }\n\n /// @notice Reverts if a certain action is paused on a market\n function checkActionPauseState(address market, Action action) internal view {\n require(!actionPaused(market, action), \"action is paused\");\n }\n\n /// @notice Reverts if the caller is not admin\n function ensureAdmin() internal view {\n require(msg.sender == admin, \"only admin can\");\n }\n\n /// @notice Checks the passed address is nonzero\n function ensureNonzeroAddress(address someone) internal pure {\n require(someone != address(0), \"can't be zero address\");\n }\n\n /// @notice Reverts if the market is not listed\n function ensureListed(Market storage market) internal view {\n require(market.isListed, \"market not listed\");\n }\n\n /// @notice Reverts if the caller is neither admin nor the passed address\n function ensureAdminOr(address privilegedAddress) internal view {\n require(msg.sender == admin || msg.sender == privilegedAddress, \"access denied\");\n }\n\n /// @notice Checks the caller is allowed to call the specified fuction\n function ensureAllowed(string memory functionSig) internal view {\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \"access denied\");\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param action Action id\n * @param market vToken address\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][uint256(action)];\n }\n\n /**\n * @notice Get the latest block number\n */\n function getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Get the latest block number with the safe32 check\n */\n function getBlockNumberAsUint32() internal view returns (uint32) {\n return safe32(getBlockNumber(), \"block # > 32 bits\");\n }\n\n /**\n * @notice Transfer XVS to VAI Vault\n */\n function releaseToVault() internal {\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\n return;\n }\n\n IERC20 xvs_ = IERC20(xvs);\n\n uint256 xvsBalance = xvs_.balanceOf(address(this));\n if (xvsBalance == 0) {\n return;\n }\n\n uint256 actualAmount;\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\n // releaseAmount = venusVAIVaultRate * deltaBlocks\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\n\n if (xvsBalance >= releaseAmount_) {\n actualAmount = releaseAmount_;\n } else {\n actualAmount = xvsBalance;\n }\n\n if (actualAmount < minReleaseAmount) {\n return;\n }\n\n releaseStartBlock = getBlockNumber();\n\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\n emit DistributedVAIVaultVenus(actualAmount);\n\n IVAIVault(vaiVaultAddress).updatePendingRewards();\n }\n\n /**\n * @notice Computes hypothetical account liquidity after applying the given redeem/borrow amounts.\n * Use this in state-changing contexts (hooks, claim flows, pool selection).\n * When `weightingStrategy` is USE_COLLATERAL_FACTOR, calls `_updateProtectionStates` before\n * delegating to the lens, which updates the bounded price and enables protection if the deviation\n * exceeds the threshold.\n * @param account The account to determine liquidity for\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param redeemTokens The number of vTokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\n * @return err Possible error code\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\n */\n function getHypotheticalAccountLiquidityInternal(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n WeightFunction weightingStrategy\n ) internal returns (Error, uint256, uint256) {\n // Populate the DBO transient price cache (EIP-1153) for all entered assets.\n // Required on the CF path so bounded prices are computed once and reused\n // by view functions (e.g. getBoundedCollateralPriceView / getBoundedDebtPriceView)\n // within the same transaction.\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\n _updateProtectionStates(account);\n }\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\n address(this),\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount,\n weightingStrategy\n );\n return (Error(err), liquidity, shortfall);\n }\n\n /**\n * @notice View-only variant: reads bounded prices from the DeviationBoundedOracle without updating\n * the transient cache. Use this only in external view functions where state mutation is not\n * permitted. On write paths use `getHypotheticalAccountLiquidityInternal` instead.\n * @dev If `getHypotheticalAccountLiquidityInternal` (or any code that calls `_updateProtectionStates`)\n * was already executed earlier in the same transaction, the DBO transient cache will already be\n * populated and this function will read from it gas-efficiently — no recomputation occurs.\n * If called in a standalone view context (cold cache), the DBO must compute bounded prices from\n * scratch on each call; results are still correct but cost more gas.\n * @param account The account to determine liquidity for\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param redeemTokens The number of vTokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\n * @return err Possible error code\n * @return liquidity Hypothetical excess liquidity above collateral requirements (0 if in shortfall)\n * @return shortfall Hypothetical shortfall below collateral requirements (0 if solvent)\n */\n function getHypotheticalAccountLiquidityInternalView(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount,\n WeightFunction weightingStrategy\n ) internal view returns (Error, uint256, uint256) {\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\n address(this),\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount,\n weightingStrategy\n );\n return (Error(err), liquidity, shortfall);\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n * @return Success indicator for whether the market was entered\n */\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = getCorePoolMarket(address(vToken));\n ensureListed(marketToJoin);\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return Error.NO_ERROR;\n }\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n\n return Error.NO_ERROR;\n }\n\n /**\n * @notice Checks for the user is allowed to redeem tokens\n * @param vToken Address of the market\n * @param redeemer Address of the user\n * @param redeemTokens Amount of tokens to redeem\n * @return Success indicator for redeem is allowed or not\n */\n function redeemAllowedInternal(address vToken, address redeemer, uint256 redeemTokens) internal returns (uint256) {\n ensureListed(getCorePoolMarket(vToken));\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!getCorePoolMarket(vToken).accountMembership[redeemer]) {\n return uint256(Error.NO_ERROR);\n }\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Returns the XVS address\n * @return The address of XVS token\n */\n function getXVSAddress() external view returns (address) {\n return xvs;\n }\n\n /**\n * @notice Returns the unique market index for the given poolId and vToken pair\n * @dev Computes a unique key for a (poolId, market) pair used in the `_poolMarkets` mapping\n * - For the core pool (`poolId == 0`), this results in the address being left-padded to 32 bytes,\n * maintaining backward compatibility with legacy mappings\n * - For other pools, packs the `poolId` and `market` address into a single `bytes32` key,\n * The first 96 bits are used for the `poolId`, and the remaining 160 bits for the `market` address\n * @param poolId The ID of the pool\n * @param vToken The address of the market (vToken)\n * @return PoolMarketId The `bytes32` key that uniquely represents the (poolId, vToken) pair\n */\n function getPoolMarketIndex(uint96 poolId, address vToken) public pure returns (PoolMarketId) {\n return PoolMarketId.wrap(bytes32((uint256(poolId) << 160) | uint160(vToken)));\n }\n\n /**\n * @dev Returns the Market struct for the given vToken in the Core Pool (`poolId = 0`)\n * @param vToken The vToken address for which the market details are requested\n * @return market The Market struct corresponding to the (corePoolId, vToken) pair\n */\n function getCorePoolMarket(address vToken) internal view returns (Market storage) {\n return _poolMarkets[getPoolMarketIndex(corePoolId, address(vToken))];\n }\n\n /**\n * @notice Updates the DeviationBoundedOracle protection state for all assets the account has entered\n * @dev This populates the transient price cache so subsequent view calls in the same transaction\n * are gas-efficient. Should be called before any liquidity calculation in the CF path.\n * @param account The account whose collateral assets need protection state updates\n */\n function _updateProtectionStates(address account) internal {\n IDeviationBoundedOracle boundedOracle = deviationBoundedOracle;\n VToken[] memory assets = accountAssets[account];\n uint256 len = assets.length;\n for (uint256 i; i < len; ++i) {\n boundedOracle.updateProtectionState(address(assets[i]));\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/FlashLoanFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IFlashLoanFacet } from \"../interfaces/IFlashLoanFacet.sol\";\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { FacetBase } from \"./FacetBase.sol\";\nimport { IFlashLoanReceiver } from \"../../../FlashLoan/interfaces/IFlashLoanReceiver.sol\";\nimport { ReentrancyGuardTransient } from \"../../../Utils/ReentrancyGuardTransient.sol\";\n\n/**\n * @title FlashLoanFacet\n * @author Venus\n * @notice This facet contains all the methods related to flash loans\n * @dev This contract implements flash loan functionality allowing users to borrow assets temporarily\n * within a single transaction. Users can borrow multiple assets simultaneously and have the\n * flexibility to repay partially, with unpaid balances automatically converted to debt positions.\n * The contract supports protocol fee collection and integrates with the Venus lending protocol.\n */\ncontract FlashLoanFacet is IFlashLoanFacet, FacetBase, ReentrancyGuardTransient {\n /// @notice Maximum number of assets that can be flash loaned in a single transaction\n uint256 public constant MAX_FLASHLOAN_ASSETS = 200;\n\n /// @notice Emitted when the flash loan is successfully executed\n event FlashLoanExecuted(address indexed receiver, VToken[] assets, uint256[] amounts);\n\n /// @notice Emitted when a flash loan is repaid (fully or partially) and shows debt position status\n event FlashLoanRepaid(\n address indexed receiver,\n address indexed onBehalf,\n address indexed asset,\n uint256 repaidAmount,\n uint256 remainingDebt\n );\n\n /**\n * @notice Executes a flashLoan operation with the requested assets.\n * @dev Transfers the specified assets to the receiver contract and handles repayment.\n * @param onBehalf The address of the user whose debt position will be used for the flashLoan.\n * @param receiver The address of the contract that will receive the flashLoan amount and execute the operation.\n * @param vTokens The addresses of the vToken assets to be loaned.\n * @param underlyingAmounts The amounts of each underlying assets to be loaned.\n * @param param The bytes passed in the executeOperation call.\n * @custom:error FlashLoanNotEnabled is thrown if the flash loan is not enabled for the asset.\n * @custom:error FlashLoanPausedSystemWide is thrown if flash loans are paused system-wide.\n * @custom:error InvalidAmount is thrown if the requested amount is zero.\n * @custom:error TooManyAssetsRequested is thrown if the number of requested assets exceeds the maximum limit.\n * @custom:error NoAssetsRequested is thrown if no assets are requested for the flash loan.\n * @custom:error InvalidFlashLoanParams is thrown if the flash loan params are invalid.\n * @custom:error MarketNotListed is thrown if the specified vToken market is not listed.\n * @custom:error SenderNotAuthorizedForFlashLoan is thrown if the sender is not authorized to use flashloan.\n * @custom:error NotAnApprovedDelegate is thrown if `msg.sender` is not `onBehalf` or an approved delegate for `onBehalf`.\n * @custom:event Emits FlashLoanExecuted on success\n */\n function executeFlashLoan(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n bytes memory param\n ) external nonReentrant {\n if (flashLoanPaused) {\n revert FlashLoanPausedSystemWide();\n }\n\n ensureNonzeroAddress(onBehalf);\n\n uint256 len = vTokens.length;\n Market storage market;\n\n // vTokens array must not be empty\n if (len == 0) {\n revert NoAssetsRequested();\n }\n // Add maximum array length check to prevent gas limit issues\n if (len > MAX_FLASHLOAN_ASSETS) {\n revert TooManyAssetsRequested(len, MAX_FLASHLOAN_ASSETS);\n }\n\n // All arrays must have the same length and not be zero\n if (len != underlyingAmounts.length) {\n revert InvalidFlashLoanParams();\n }\n\n for (uint256 i; i < len; ++i) {\n market = getCorePoolMarket(address(vTokens[i]));\n if (!market.isListed) {\n revert MarketNotListed(address(vTokens[i]));\n }\n if (!(vTokens[i]).isFlashLoanEnabled()) {\n revert FlashLoanNotEnabled();\n }\n if (underlyingAmounts[i] == 0) {\n revert InvalidAmount();\n }\n }\n\n ensureNonzeroAddress(receiver);\n\n if (!authorizedFlashLoan[msg.sender]) {\n revert SenderNotAuthorizedForFlashLoan(msg.sender);\n }\n\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\n revert NotAnApprovedDelegate();\n }\n\n // Execute flash loan phases\n _executeFlashLoanPhases(onBehalf, receiver, vTokens, underlyingAmounts, param);\n\n emit FlashLoanExecuted(receiver, vTokens, underlyingAmounts);\n }\n\n /**\n * @notice Executes all flash loan phases in sequence\n * @dev Orchestrates the complete flash loan process through three phases:\n * Phase 1: Calculate fees and transfer assets to receiver\n * Phase 2: Execute custom operations on receiver contract\n * Phase 3: Handle repayment and debt position creation\n * @param onBehalf The address whose debt position will be used for any unpaid flash loan balance\n * @param receiver The address of the contract receiving the flash loan\n * @param vTokens Array of vToken contracts for the assets being borrowed\n * @param underlyingAmounts Array of amounts being borrowed for each asset\n * @param param Additional parameters passed to the receiver contract\n */\n function _executeFlashLoanPhases(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n bytes memory param\n ) internal {\n FlashLoanFee memory flashLoanData;\n //Cache array length\n uint256 vTokensLength = vTokens.length;\n // Initialize arrays\n flashLoanData.totalFees = new uint256[](vTokensLength);\n flashLoanData.protocolFees = new uint256[](vTokensLength);\n\n // Phase 1: Calculate fees and transfer assets\n _executePhase1(receiver, vTokens, underlyingAmounts, flashLoanData);\n // Phase 2: Execute operations on receiver contract\n uint256[] memory tokensApproved = _executePhase2(\n onBehalf,\n receiver,\n vTokens,\n underlyingAmounts,\n flashLoanData.totalFees,\n param\n );\n // Phase 3: Handles repayment\n _executePhase3(onBehalf, receiver, vTokens, underlyingAmounts, tokensApproved, flashLoanData);\n }\n\n /**\n * @notice Phase 1: Calculate fees and transfer assets to receiver\n * @dev For each requested asset:\n * - Calculates total fee and protocol fee using the vToken's fee structure\n * - Transfers the requested amount from the vToken to the receiver\n * - Updates flash loan tracking in the vToken contract\n * @param receiver The address receiving the flash loan assets\n * @param vTokens Array of vToken contracts for the assets being borrowed\n * @param underlyingAmounts Array of amounts being borrowed for each asset\n * @param flashLoanData Struct containing fee arrays to be populated\n */\n function _executePhase1(\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n FlashLoanFee memory flashLoanData\n ) internal {\n //Cache array length\n uint256 vTokensLength = vTokens.length;\n\n for (uint256 i; i < vTokensLength; ++i) {\n (flashLoanData.totalFees[i], flashLoanData.protocolFees[i]) = vTokens[i].calculateFlashLoanFee(\n underlyingAmounts[i]\n );\n\n // Transfer the asset to receiver\n vTokens[i].transferOutUnderlyingFlashLoan(receiver, underlyingAmounts[i]);\n }\n }\n\n /**\n * @notice Phase 2: Execute custom operations on receiver contract\n * @dev Calls the receiver contract's executeOperation function, allowing it to perform\n * custom logic with the borrowed assets. The receiver must return success status\n * and specify repayment amounts for each asset.\n * @param onBehalf The address whose debt position will be used for any unpaid balance\n * @param receiver The address of the contract executing custom operations\n * @param vTokens Array of vToken contracts for the borrowed assets\n * @param underlyingAmounts Array of amounts that were borrowed for each asset\n * @param totalFees Array of total fees for each borrowed asset\n * @param param Additional parameters passed to the receiver's executeOperation function\n * @return tokensApproved Array of amounts the receiver approved for repayment\n * @custom:error ExecuteFlashLoanFailed is thrown if the receiver's executeOperation returns false\n */\n function _executePhase2(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n uint256[] memory totalFees,\n bytes memory param\n ) internal returns (uint256[] memory) {\n (bool success, uint256[] memory tokensApproved) = IFlashLoanReceiver(receiver).executeOperation(\n vTokens,\n underlyingAmounts,\n totalFees,\n msg.sender,\n onBehalf,\n param\n );\n\n if (!success) {\n revert ExecuteFlashLoanFailed();\n }\n return tokensApproved;\n }\n\n /**\n * @notice Phase 3: Handles repayment based on full or partial repayment\n * @dev Processes repayment for each asset in the flash loan:\n * - Ensures minimum fee repayment for each asset\n * - Creates debt positions for any unpaid balances\n * - Handles protocol fee distribution automatically\n * @param onBehalf The address whose debt position will be used for any unpaid balance\n * @param receiver The address providing the repayment\n * @param vTokens Array of vToken contracts for the borrowed assets\n * @param underlyingAmounts Array of amounts that were originally borrowed for each asset\n * @param underlyingAmountsToRepay Array of amounts to be repaid for each asset\n * @param flashLoanData Struct containing calculated fees for each asset\n */\n function _executePhase3(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n uint256[] memory underlyingAmountsToRepay,\n FlashLoanFee memory flashLoanData\n ) internal {\n //Cache array length\n uint256 vTokensLength = vTokens.length;\n\n for (uint256 i; i < vTokensLength; ++i) {\n _handleFlashLoan(\n vTokens[i],\n onBehalf,\n receiver,\n underlyingAmounts[i],\n underlyingAmountsToRepay[i],\n flashLoanData.totalFees[i],\n flashLoanData.protocolFees[i]\n );\n }\n }\n\n /**\n * @notice Handles the repayment and fee logic for a flash loan.\n * @dev This function processes flash loan repayment with the following logic:\n * 1. Ensures the repayment amount is at least equal to the total fee (minimum requirement).\n * 2. Caps the repayment to prevent over-repayment (borrowedAmount + totalFee maximum).\n * 3. Transfers the actual repayment amount from the receiver to the vToken.\n * 4. If repayment is less than the full amount (borrowedAmount + totalFee), creates a debt position\n * for the unpaid balance on the onBehalf address.\n * 5. Protocol fees are automatically handled within the transferInUnderlyingFlashLoan function.\n * @param vToken The vToken contract for the asset being flash loaned.\n * @param onBehalf The address whose debt position will be used if there is any unpaid flash loan balance.\n * @param receiver The address that received the flash loan and is providing the repayment.\n * @param borrowedAmount The original amount that was borrowed (passed from underlyingAmounts).\n * @param repayAmount The amount being repaid by the receiver (may be partial or full repayment).\n * @param totalFee The total fee charged for the flash loan (minimum required repayment).\n * @param protocolFee The portion of the total fee allocated to the protocol.\n * @custom:error NotEnoughRepayment is thrown if repayAmount is less than the minimum required fee.\n * @custom:error FailedToCreateDebtPosition is thrown if debt position creation fails for unpaid balance.\n */\n function _handleFlashLoan(\n VToken vToken,\n address payable onBehalf,\n address payable receiver,\n uint256 borrowedAmount,\n uint256 repayAmount,\n uint256 totalFee,\n uint256 protocolFee\n ) internal {\n uint256 maxExpectedRepayment = borrowedAmount + totalFee;\n uint256 actualRepayAmount = repayAmount > maxExpectedRepayment ? maxExpectedRepayment : repayAmount;\n\n if (actualRepayAmount < totalFee) {\n revert NotEnoughRepayment(actualRepayAmount, totalFee);\n }\n\n // Transfer repayment (this will handle the protocol fee as well)\n uint256 actualAmountTransferred = vToken.transferInUnderlyingFlashLoan(\n receiver,\n actualRepayAmount,\n totalFee,\n protocolFee\n );\n\n // Default for full repayment\n uint256 leftUnpaidBalance;\n\n if (maxExpectedRepayment > actualAmountTransferred) {\n // If there is any unpaid balance, it becomes an ongoing debt\n leftUnpaidBalance = maxExpectedRepayment - actualAmountTransferred;\n\n uint256 debtError = vToken.flashLoanDebtPosition(onBehalf, leftUnpaidBalance);\n if (debtError != 0) {\n revert FailedToCreateDebtPosition();\n }\n }\n\n // Emit event for partial repayment with debt position creation\n emit FlashLoanRepaid(\n receiver,\n onBehalf,\n address(vToken.underlying()),\n actualAmountTransferred,\n leftUnpaidBalance\n );\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/MarketFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { IMarketFacet } from \"../interfaces/IMarketFacet.sol\";\nimport { FacetBase } from \"./FacetBase.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\nimport { WeightFunction } from \"../interfaces/IFacetBase.sol\";\n\n/**\n * @title MarketFacet\n * @author Venus\n * @dev This facet contains all the methods related to the market's management in the pool\n * @notice This facet contract contains functions regarding markets\n */\ncontract MarketFacet is IMarketFacet, FacetBase {\n /// @notice Emitted when an admin supports a market\n event MarketListed(VToken indexed vToken);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account\n event DelegateUpdated(address indexed approver, address indexed delegate, bool approved);\n\n /// @notice Emitted when an admin unlists a market\n event MarketUnlisted(address indexed vToken);\n\n /// @notice Emitted when a market is initialized in a pool\n event PoolMarketInitialized(uint96 indexed poolId, address indexed market);\n\n /// @notice Emitted when a user enters or exits a pool (poolId = 0 means exit)\n event PoolSelected(address indexed account, uint96 previousPoolId, uint96 indexed newPoolId);\n\n /// @notice Emitted when a vToken market is removed from a pool\n event PoolMarketRemoved(uint96 indexed poolId, address indexed vToken);\n\n /// @notice Emitted when a new pool is created\n event PoolCreated(uint96 indexed poolId, string label);\n\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() public pure returns (bool) {\n return true;\n }\n\n /**\n * @notice Returns the vToken markets an account has entered in the Core Pool\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\n * @param account The address of the account to query\n * @return assets A dynamic array of vToken markets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n uint256 len;\n VToken[] memory _accountAssets = accountAssets[account];\n uint256 _accountAssetsLength = _accountAssets.length;\n\n VToken[] memory assetsIn = new VToken[](_accountAssetsLength);\n\n for (uint256 i; i < _accountAssetsLength; ++i) {\n Market storage market = getCorePoolMarket(address(_accountAssets[i]));\n if (market.isListed) {\n assetsIn[len] = _accountAssets[i];\n ++len;\n }\n }\n\n assembly {\n mstore(assetsIn, len)\n }\n\n return assetsIn;\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market\n * @return The list of market addresses\n */\n function getAllMarkets() external view returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\n address(this),\n vTokenBorrowed,\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param borrower Address of borrower whose collateral is being seized\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address borrower,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\n borrower,\n address(this),\n vTokenBorrowed,\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\n address(this),\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Returns whether the given account has entered the specified vToken market in the Core Pool\n * @dev Reads membership from the Core Pool (`poolId = 0`). Although the account may have entered other pools,\n * all entered market state is recorded in the Core Pool indexes, making this function applicable to all poolIds\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the asset, otherwise false\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return getCorePoolMarket(address(vToken)).accountMembership[account];\n }\n\n /**\n * @notice Checks whether the given vToken market is listed in the Core Pool (`poolId = 0`)\n * @param vToken The vToken Address of the market to check\n * @return listed True if the (Core Pool, vToken) market is listed, otherwise false\n */\n function isMarketListed(VToken vToken) external view returns (bool) {\n return getCorePoolMarket(address(vToken)).isListed;\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return Success indicator for whether each corresponding market was entered\n */\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\n }\n\n return results;\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @dev Only callable by the account itself or an approved delegate\n * @param onBehalf The address of the account entering the market\n * @param vToken The address of the vToken market to enable for the account\n * @return uint256 indicating the result (0 = success, non-zero = failure)\n * @custom:error NotAnApprovedDelegate thrown if `msg.sender` is not the account itself or an approved delegate\n */\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256) {\n if (msg.sender != onBehalf && !approvedDelegates[onBehalf][msg.sender]) {\n revert NotAnApprovedDelegate();\n }\n return uint256(addToMarketInternal(VToken(vToken), onBehalf));\n }\n\n /**\n * @notice Unlists the given vToken market from the Core Pool (`poolId = 0`) by setting `isListed` to false\n * @dev Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\n * @param market The address of the market (vToken) to unlist\n * @return uint256 0=success, otherwise a failure (See enum Error for details)\n */\n function unlistMarket(address market) external returns (uint256) {\n ensureAllowed(\"unlistMarket(address)\");\n\n Market storage _market = getCorePoolMarket(market);\n\n if (!_market.isListed) {\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.UNLIST_MARKET_NOT_LISTED);\n }\n\n require(actionPaused(market, Action.BORROW), \"borrow action is not paused\");\n require(actionPaused(market, Action.MINT), \"mint action is not paused\");\n require(actionPaused(market, Action.REDEEM), \"redeem action is not paused\");\n require(actionPaused(market, Action.REPAY), \"repay action is not paused\");\n require(actionPaused(market, Action.ENTER_MARKET), \"enter market action is not paused\");\n require(actionPaused(market, Action.LIQUIDATE), \"liquidate action is not paused\");\n require(actionPaused(market, Action.SEIZE), \"seize action is not paused\");\n require(actionPaused(market, Action.TRANSFER), \"transfer action is not paused\");\n require(actionPaused(market, Action.EXIT_MARKET), \"exit market action is not paused\");\n\n require(borrowCaps[market] == 0, \"borrow cap is not 0\");\n require(supplyCaps[market] == 0, \"supply cap is not 0\");\n\n require(_market.collateralFactorMantissa == 0, \"collateral factor is not 0\");\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow\n * @param vTokenAddress The address of the asset to be removed\n * @return Whether or not the account successfully exited the market\n */\n function exitMarket(address vTokenAddress) external returns (uint256) {\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\n require(oErr == 0, \"getAccountSnapshot failed\"); // semi-opaque error code\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\n if (allowed != 0) {\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\n }\n\n Market storage marketToExit = getCorePoolMarket(address(vToken));\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return uint256(Error.NO_ERROR);\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n uint256 i;\n for (; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n userAssetList[i] = userAssetList[len - 1];\n userAssetList.pop();\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(i < len);\n\n emit MarketExited(vToken, msg.sender);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _supportMarket to support the Isolated Lending Comptroller Interface\n * @param vToken The address of the market (token) to list\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function supportMarket(VToken vToken) external returns (uint256) {\n return __supportMarket(vToken);\n }\n\n /**\n * @notice Adds the given vToken market to the Core Pool (`poolId = 0`) and marks it as listed\n * @dev Allows a privileged role to add and list markets to the Comptroller\n * @param vToken The address of the vToken market to list in the Core Pool\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _supportMarket(VToken vToken) external returns (uint256) {\n return __supportMarket(vToken);\n }\n\n /**\n * @notice Grants or revokes the borrowing or redeeming delegate rights to / from an account\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\n * will see the debt on their account\n * Upon a delegated redeem, the delegate will receive the redeemed amount and the approver\n * will see a deduction in his vToken balance\n * @param delegate The address to update the rights for\n * @param approved Whether to grant (true) or revoke (false) the borrowing or redeeming rights\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n require(approvedDelegates[msg.sender][delegate] != approved, \"Delegation status unchanged\");\n\n _updateDelegate(msg.sender, delegate, approved);\n }\n\n /**\n * @notice Allows a user to switch to a new pool (e.g., e-mode ).\n * @param poolId The ID of the pool the user wants to enter.\n * @custom:error PoolDoesNotExist The specified pool ID does not exist.\n * @custom:error AlreadyInSelectedPool The user is already in the target pool.\n * @custom:error IncompatibleBorrowedAssets The user's current borrows are incompatible with the new pool.\n * @custom:error LiquidityCheckFailed The user's liquidity is insufficient after switching pools.\n * @custom:error InactivePool The user is trying to enter inactive pool.\n * @custom:event PoolSelected Emitted after a successful pool switch.\n */\n function enterPool(uint96 poolId) external {\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n\n if (poolId == userPoolId[msg.sender]) {\n revert AlreadyInSelectedPool();\n }\n\n if (poolId != corePoolId && !pools[poolId].isActive) {\n revert InactivePool(poolId);\n }\n\n if (!hasValidPoolBorrows(msg.sender, poolId)) {\n revert IncompatibleBorrowedAssets();\n }\n\n emit PoolSelected(msg.sender, userPoolId[msg.sender], poolId);\n\n userPoolId[msg.sender] = poolId;\n\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n msg.sender,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n if (err != Error.NO_ERROR || shortfall > 0) {\n revert LiquidityCheckFailed(uint256(err), shortfall);\n }\n }\n\n /**\n * @notice Creates a new pool with the given label.\n * @param label name for the pool (must be non-empty).\n * @return poolId The incremental unique identifier of the newly created pool.\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string.\n * @custom:event PoolCreated Emitted after successfully creating a new pool.\n */\n function createPool(string memory label) external returns (uint96) {\n ensureAllowed(\"createPool(string)\");\n\n if (bytes(label).length == 0) {\n revert EmptyPoolLabel();\n }\n\n uint96 poolId = ++lastPoolId;\n PoolData storage newPool = pools[poolId];\n newPool.label = label;\n newPool.isActive = true;\n\n emit PoolCreated(poolId, label);\n return poolId;\n }\n\n /**\n * @notice Batch initializes market entries with basic config.\n * @param poolIds Array of pool IDs.\n * @param vTokens Array of market (vToken) addresses.\n * @custom:error ArrayLengthMismatch Reverts if `poolIds` and `vTokens` arrays have different lengths or if the length is zero.\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\n * @custom:error MarketNotListedInCorePool Reverts if the market is not listed in the core pool.\n * @custom:error MarketAlreadyListed Reverts if the given market is already listed in the specified pool.\n * @custom:error InactivePool Reverts if attempted to add markets to an inactive pool.\n * @custom:event PoolMarketInitialized Emitted after successfully initializing a market in a pool.\n */\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external {\n ensureAllowed(\"addPoolMarkets(uint96[],address[])\");\n\n uint256 len = poolIds.length;\n if (len == 0 || len != vTokens.length) {\n revert ArrayLengthMismatch();\n }\n\n for (uint256 i; i < len; i++) {\n _addPoolMarket(poolIds[i], vTokens[i]);\n }\n }\n\n /**\n * @notice Removes a market (vToken) from the specified pool.\n * @param poolId The ID of the pool from which the market should be removed.\n * @param vToken The address of the market token to remove.\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\n * @custom:error PoolMarketNotFound Reverts if the market is not listed in the pool.\n * @custom:event PoolMarketRemoved Emitted after a market is successfully removed from a pool.\n */\n function removePoolMarket(uint96 poolId, address vToken) external {\n ensureAllowed(\"removePoolMarket(uint96,address)\");\n\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\n if (!_poolMarkets[index].isListed) {\n revert PoolMarketNotFound(poolId, vToken);\n }\n\n address[] storage assets = pools[poolId].vTokens;\n\n uint256 length = assets.length;\n for (uint256 i; i < length; i++) {\n if (assets[i] == vToken) {\n assets[i] = assets[length - 1];\n assets.pop();\n break;\n }\n }\n\n delete _poolMarkets[index];\n\n emit PoolMarketRemoved(poolId, vToken);\n }\n\n /**\n * @notice Get the core pool collateral factor for a vToken\n * @param vToken The address of the vToken to get the collateral factor for\n * @return The collateral factor for the vToken, scaled by 1e18\n */\n function getCollateralFactor(address vToken) external view returns (uint256) {\n (uint256 cf, , ) = getLiquidationParams(corePoolId, vToken);\n return cf;\n }\n\n /**\n * @notice Get the core pool liquidation threshold for a vToken\n * @param vToken The address of the vToken to get the liquidation threshold for\n * @return The liquidation threshold for the vToken, scaled by 1e18\n */\n function getLiquidationThreshold(address vToken) external view returns (uint256) {\n (, uint256 lt, ) = getLiquidationParams(corePoolId, vToken);\n return lt;\n }\n\n /**\n * @notice Get the core pool liquidation Incentive for a vToken\n * @param vToken The address of the vToken to get the liquidation Incentive for\n * @return liquidationIncentive The liquidation incentive for the vToken, scaled by 1e18\n */\n function getLiquidationIncentive(address vToken) external view returns (uint256) {\n (, , uint256 li) = getLiquidationParams(corePoolId, vToken);\n return li;\n }\n\n /**\n * @notice Get the effective loan-to-value factor (collateral factor or liquidation threshold) for a given account and market.\n * @dev The value is determined by the pool entered by the account and the specified vToken via\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used.\n * This value is used for account liquidity calculations and liquidation checks.\n * @param account The account whose pool is used to determine the market's risk parameters.\n * @param vToken The address of the vToken market.\n * @param weightingStrategy The weighting strategy to use:\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\n * @return factor The effective loan-to-value factor, scaled by 1e18.\n */\n function getEffectiveLtvFactor(\n address account,\n address vToken,\n WeightFunction weightingStrategy\n ) external view returns (uint256) {\n (uint256 cf, uint256 lt, ) = getLiquidationParams(userPoolId[account], vToken);\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) return cf;\n else if (weightingStrategy == WeightFunction.USE_LIQUIDATION_THRESHOLD) return lt;\n else revert InvalidWeightingStrategy(weightingStrategy);\n }\n\n /**\n * @notice Get the Effective Liquidation Incentive for a given account and market\n * @dev The incentive is determined by the pool entered by the account and the specified vToken via\n * `getLiquidationParams()`. If the pool is inactive, or if the vToken is not configured in the\n * account's pool and `allowCorePoolFallback` is enabled, the core pool (poolId = 0) values are used\n * @param account The account whose pool is used to determine the market's risk parameters\n * @param vToken The address of the vToken market\n * @return The liquidation Incentive for the vToken, scaled by 1e18\n */\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256) {\n (, , uint256 li) = getLiquidationParams(userPoolId[account], vToken);\n return li;\n }\n\n /**\n * @notice Returns the full list of vTokens for a given pool ID.\n * @param poolId The ID of the pool whose vTokens are being queried.\n * @return An array of vToken addresses associated with the pool.\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\n * @custom:error InvalidOperationForCorePool Reverts if called on the Core Pool.\n */\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory) {\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n return pools[poolId].vTokens;\n }\n\n /**\n * @notice Returns the market configuration for a vToken in the core pool (poolId = 0).\n * @dev Fetches the Market struct associated with the core pool and returns all relevant parameters.\n * @param vToken The address of the vToken whose market configuration is to be fetched.\n * @return isListed Whether the market is listed and enabled.\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\n * @return isVenus Whether this market is eligible for VENUS rewards.\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\n * @return liquidationIncentiveMantissa The max liquidation incentive allowed for this market, in mantissa.\n * @return marketPoolId The pool ID this market belongs to.\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\n */\n function markets(\n address vToken\n )\n external\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n )\n {\n return poolMarkets(corePoolId, vToken);\n }\n\n /**\n * @notice Returns the market configuration for a vToken from _poolMarkets.\n * @dev Fetches the Market struct associated with the poolId and returns all relevant parameters.\n * @param poolId The ID of the pool whose market configuration is being queried.\n * @param vToken The address of the vToken whose market configuration is to be fetched.\n * @return isListed Whether the market is listed and enabled.\n * @return collateralFactorMantissa The maximum borrowable percentage of collateral, in mantissa.\n * @return isVenus Whether this market is eligible for XVS rewards.\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\n * @return marketPoolId The pool ID this market belongs to.\n * @return isBorrowAllowed Whether borrowing is allowed in this market.\n * @custom:error PoolDoesNotExist Reverts if the given pool ID do not exist.\n */\n function poolMarkets(\n uint96 poolId,\n address vToken\n )\n public\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n )\n {\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n PoolMarketId key = getPoolMarketIndex(poolId, vToken);\n Market storage m = _poolMarkets[key];\n\n return (\n m.isListed,\n m.collateralFactorMantissa,\n m.isVenus,\n m.liquidationThresholdMantissa,\n m.liquidationIncentiveMantissa,\n m.poolId,\n m.isBorrowAllowed\n );\n }\n\n /**\n * @notice Returns true if the user can switch to the given target pool, i.e.,\n * all markets they have borrowed from are also borrowable in the target pool.\n * @param account The address of the user attempting to switch pools.\n * @param targetPoolId The pool ID the user wants to switch into.\n * @return bool True if the switch is allowed, otherwise False.\n */\n function hasValidPoolBorrows(address account, uint96 targetPoolId) public view returns (bool) {\n VToken[] memory assets = accountAssets[account];\n if (targetPoolId != corePoolId && mintedVAIs[account] > 0) {\n return false;\n }\n\n for (uint256 i; i < assets.length; i++) {\n VToken vToken = assets[i];\n PoolMarketId index = getPoolMarketIndex(targetPoolId, address(vToken));\n\n if (!_poolMarkets[index].isBorrowAllowed) {\n if (vToken.borrowBalanceStored(account) > 0) {\n return false;\n }\n }\n }\n return true;\n }\n\n function _updateDelegate(address approver, address delegate, bool approved) internal {\n approvedDelegates[approver][delegate] = approved;\n emit DelegateUpdated(approver, delegate, approved);\n }\n\n function _addMarketInternal(VToken vToken) internal {\n uint256 allMarketsLength = allMarkets.length;\n for (uint256 i; i < allMarketsLength; ++i) {\n require(allMarkets[i] != vToken, \"already added\");\n }\n allMarkets.push(vToken);\n }\n\n function _initializeMarket(address vToken) internal {\n uint32 blockNumber = getBlockNumberAsUint32();\n\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = venusInitialIndex;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = venusInitialIndex;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n function __supportMarket(VToken vToken) internal returns (uint256) {\n ensureAllowed(\"_supportMarket(address)\");\n\n if (getCorePoolMarket(address(vToken)).isListed) {\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\n }\n\n vToken.isVToken(); // Sanity check to make sure its really a VToken\n\n // Note that isVenus is not in active use anymore\n Market storage newMarket = getCorePoolMarket(address(vToken));\n newMarket.isListed = true;\n newMarket.isVenus = false;\n newMarket.collateralFactorMantissa = 0;\n\n _addMarketInternal(vToken);\n _initializeMarket(address(vToken));\n\n emit MarketListed(vToken);\n\n return uint256(Error.NO_ERROR);\n }\n\n function _addPoolMarket(uint96 poolId, address vToken) internal {\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (!pools[poolId].isActive) revert InactivePool(poolId);\n\n // Core Pool Index\n PoolMarketId index = getPoolMarketIndex(corePoolId, vToken);\n if (!_poolMarkets[index].isListed) revert MarketNotListedInCorePool();\n\n // Pool Index\n index = getPoolMarketIndex(poolId, vToken);\n if (_poolMarkets[index].isListed) revert MarketAlreadyListed(poolId, vToken);\n\n Market storage m = _poolMarkets[index];\n m.poolId = poolId;\n m.isListed = true;\n\n pools[poolId].vTokens.push(vToken);\n\n emit PoolMarketInitialized(poolId, vToken);\n }\n\n /**\n * @notice Returns only the core risk parameters (CF, LI, LT) for a vToken in a specific pool.\n * @dev If the pool is inactive, or if the vToken is not configured in the given pool and\n * `allowCorePoolFallback` is enabled, falls back to the core pool (poolId = 0) values.\n * @return collateralFactorMantissa The max borrowable percentage of collateral, in mantissa.\n * @return liquidationThresholdMantissa The threshold at which liquidation is triggered, in mantissa.\n * @return liquidationIncentiveMantissa The liquidation incentive allowed for this market, in mantissa.\n */\n function getLiquidationParams(\n uint96 poolId,\n address vToken\n )\n internal\n view\n returns (\n uint256 collateralFactorMantissa,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa\n )\n {\n PoolData storage pool = pools[poolId];\n Market storage market;\n\n if (poolId == corePoolId || !pool.isActive) {\n market = getCorePoolMarket(vToken);\n } else {\n PoolMarketId poolKey = getPoolMarketIndex(poolId, vToken);\n Market storage poolMarket = _poolMarkets[poolKey];\n market = (!poolMarket.isListed && pool.allowCorePoolFallback) ? getCorePoolMarket(vToken) : poolMarket;\n }\n\n return (\n market.collateralFactorMantissa,\n market.liquidationThresholdMantissa,\n market.liquidationIncentiveMantissa\n );\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/PolicyFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { IPolicyFacet } from \"../interfaces/IPolicyFacet.sol\";\n\nimport { XVSRewardsHelper } from \"./XVSRewardsHelper.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\nimport { WeightFunction } from \"../interfaces/IFacetBase.sol\";\n\n/**\n * @title PolicyFacet\n * @author Venus\n * @dev This facet contains all the hooks used while transferring the assets\n * @notice This facet contract contains all the external pre-hook functions related to vToken\n */\ncontract PolicyFacet is IPolicyFacet, XVSRewardsHelper {\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.MINT);\n ensureListed(getCorePoolMarket(vToken));\n\n uint256 supplyCap = supplyCaps[vToken];\n require(supplyCap != 0, \"market supply cap is 0\");\n\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n require(nextTotalSupply <= supplyCap, \"market supply cap reached\");\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, minter);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being minted\n * @param minter The address minting the tokens\n * @param actualMintAmount The amount of the underlying asset being minted\n * @param mintTokens The number of tokens being minted\n */\n // solhint-disable-next-line no-unused-vars\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(minter, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REDEEM);\n\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, redeemer);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being redeemed\n * @param redeemer The address redeeming the tokens\n * @param redeemAmount The amount of the underlying asset being redeemed\n * @param redeemTokens The number of tokens being redeemed\n */\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\n require(redeemTokens != 0 || redeemAmount == 0, \"redeemTokens zero\");\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.BORROW);\n ensureListed(getCorePoolMarket(vToken));\n poolBorrowAllowed(borrower, vToken);\n\n uint256 borrowCap = borrowCaps[vToken];\n require(borrowCap != 0, \"market borrow cap is 0\");\n\n if (!getCorePoolMarket(vToken).accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n require(msg.sender == vToken, \"sender must be vToken\");\n\n // attempt to add borrower to the market\n Error err = addToMarketInternal(VToken(vToken), borrower);\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n }\n\n (uint256 collateralPrice, uint256 debtPrice) = deviationBoundedOracle.getBoundedPricesView(vToken);\n if (collateralPrice == 0 || debtPrice == 0) {\n return uint256(Error.PRICE_ERROR);\n }\n\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\n require(nextTotalBorrows <= borrowCap, \"market borrow cap reached\");\n\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset whose underlying is being borrowed\n * @param borrower The address borrowing the underlying\n * @param borrowAmount The amount of the underlying asset requested to borrow\n */\n // solhint-disable-next-line no-unused-vars\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param payer The account which would repay the asset\n * @param borrower The account which borrowed the asset\n * @param repayAmount The amount of the underlying asset the account would repay\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function repayBorrowAllowed(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 repayAmount // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REPAY);\n ensureListed(getCorePoolMarket(vToken));\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being repaid\n * @param payer The address repaying the borrow\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n */\n function repayBorrowVerify(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n */\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256) {\n checkProtocolPauseState();\n\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\n return uint256(Error.UNAUTHORIZED);\n }\n\n ensureListed(getCorePoolMarket(vTokenCollateral));\n uint256 borrowBalance;\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(getCorePoolMarket(vTokenBorrowed));\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n } else {\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\n }\n\n if (isForcedLiquidationEnabled[vTokenBorrowed] || isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n return uint(Error.TOO_MUCH_REPAY);\n }\n return uint(Error.NO_ERROR);\n }\n\n /* The borrower must have shortfall in order to be liquidatable */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\n borrower,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_LIQUIDATION_THRESHOLD\n );\n\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall == 0) {\n return uint256(Error.INSUFFICIENT_SHORTFALL);\n }\n\n // The liquidator may not repay more than what is allowed by the closeFactor\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\n return uint256(Error.TOO_MUCH_REPAY);\n }\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n * @param seizeTokens The amount of collateral token that will be seized\n */\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = getCorePoolMarket(vTokenCollateral);\n\n // We've added VAIController as a borrowed token list check for seize\n ensureListed(market);\n\n if (!market.accountMembership[borrower]) {\n return uint256(Error.MARKET_NOT_COLLATERAL);\n }\n\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(getCorePoolMarket(vTokenBorrowed));\n }\n\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\n return uint256(Error.COMPTROLLER_MISMATCH);\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vTokenCollateral);\n distributeSupplierVenus(vTokenCollateral, borrower);\n distributeSupplierVenus(vTokenCollateral, liquidator);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, src);\n distributeSupplierVenus(vToken, dst);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being transferred\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n */\n // solhint-disable-next-line no-unused-vars\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(src, vToken);\n prime.accrueInterestAndUpdateScore(dst, vToken);\n }\n }\n\n /**\n * @notice Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\n * @param account The account get liquidity for\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n * account shortfall below collateral requirements)\n */\n function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\n account,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n /**\n * @notice Determine the current account liquidity wrt liquidation threshold requirements\n * @param account The account get liquidity for\n * @return (possible error code (semi-opaque),\n account liquidity in excess of liquidation threshold requirements,\n * account shortfall below liquidation threshold requirements)\n */\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\n account,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_LIQUIDATION_THRESHOLD\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return (possible error code (semi-opaque),\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternalView(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n // setter functionality\n /**\n * @notice Set XVS speed for a single market\n * @dev Allows the contract admin to set XVS speed for a market\n * @param vTokens The market whose XVS speed to update\n * @param supplySpeeds New XVS speed for supply\n * @param borrowSpeeds New XVS speed for borrow\n */\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external {\n ensureAdmin();\n\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid input\");\n\n for (uint256 i; i < numTokens; ++i) {\n ensureNonzeroAddress(address(vTokens[i]));\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n /**\n * @dev Internal function to set XVS speed for a single market\n * @param vToken The market whose XVS speed to update\n * @param supplySpeed New XVS speed for supply\n * @param borrowSpeed New XVS speed for borrow\n * @custom:event VenusSupplySpeedUpdated Emitted after the venus supply speed for a market is updated\n * @custom:event VenusBorrowSpeedUpdated Emitted after the venus borrow speed for a market is updated\n */\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n ensureListed(getCorePoolMarket(address(vToken)));\n\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n\n updateVenusSupplyIndex(address(vToken));\n // Update speed and emit event\n venusSupplySpeeds[address(vToken)] = supplySpeed;\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n\n /**\n * @dev Checks if vToken borrowing is allowed in the account's entered pool\n * Reverts if borrowing is not permitted\n * @param account The address of the account whose borrow permission is being checked\n * @param vToken The vToken market to check borrowing status for\n * @custom:error BorrowNotAllowedInPool Reverts if borrowing is not allowed in the account's entered pool\n * @custom:error InactivePool Reverts if borrowing in an inactive pool.\n */\n function poolBorrowAllowed(address account, address vToken) internal view {\n uint96 userPool = userPoolId[account];\n PoolMarketId index = getPoolMarketIndex(userPool, vToken);\n if (!_poolMarkets[index].isBorrowAllowed) {\n revert BorrowNotAllowedInPool();\n }\n if (userPool != corePoolId && !pools[userPool].isActive) {\n revert InactivePool(userPool);\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/RewardFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { IRewardFacet } from \"../interfaces/IRewardFacet.sol\";\nimport { XVSRewardsHelper } from \"./XVSRewardsHelper.sol\";\nimport { VBep20Interface } from \"../../../Tokens/VTokens/VTokenInterfaces.sol\";\nimport { WeightFunction } from \"../interfaces/IFacetBase.sol\";\n\n/**\n * @title RewardFacet\n * @author Venus\n * @dev This facet contains all the methods related to the reward functionality\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\n */\ncontract RewardFacet is IRewardFacet, XVSRewardsHelper {\n /// @notice Emitted when Venus is granted by admin\n event VenusGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when XVS are seized for the holder\n event VenusSeized(address indexed holder, uint256 amount);\n\n using SafeERC20 for IERC20;\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets and VAI\n * @param holder The address to claim XVS for\n */\n function claimVenus(address holder) public {\n return claimVenus(holder, allMarkets);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in the specified markets\n * @param holder The address to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n */\n function claimVenus(address holder, VToken[] memory vTokens) public {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, vTokens, true, true);\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\n claimVenus(holders, vTokens, borrowers, suppliers, false);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\n * @param holder The address to claim XVS for\n */\n function claimVenusAsCollateral(address holder) external {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, allMarkets, true, true, true);\n }\n\n /**\n * @notice Transfer XVS to the user with user's shortfall considered\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\n * @param user The address of the user to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n * @param shortfall The shortfall of the user\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\n * @return The amount of XVS which was NOT transferred to the user\n */\n function grantXVSInternal(\n address user,\n uint256 amount,\n uint256 shortfall,\n bool collateral\n ) internal returns (uint256) {\n // If the user is blacklisted, they can't get XVS rewards\n require(\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\n \"Blacklisted\"\n );\n\n IERC20 xvs_ = IERC20(xvs);\n\n if (amount == 0 || amount > xvs_.balanceOf(address(this))) {\n return amount;\n }\n\n if (shortfall == 0) {\n xvs_.safeTransfer(user, amount);\n return 0;\n }\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\n // anything, otherwise, we will transfer the pending xvs as collateral to\n // vXVS token and mint vXVS for the user\n //\n // If mintBehalf failed, don't grant any xvs\n require(collateral, \"bankrupt\");\n\n address xvsVToken_ = xvsVToken;\n\n xvs_.safeApprove(xvsVToken_, 0);\n xvs_.safeApprove(xvsVToken_, amount);\n require(VBep20Interface(xvsVToken_).mintBehalf(user, amount) == uint256(Error.NO_ERROR), \"mint behalf error\");\n\n // set venusAccrued[user] to 0\n return 0;\n }\n\n /*** Venus Distribution Admin ***/\n\n /**\n * @notice Transfer XVS to the recipient\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\n * Note: If there is not enough XVS, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n */\n function _grantXVS(address recipient, uint256 amount) external {\n ensureAdmin();\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\n require(amountLeft == 0, \"no xvs\");\n emit VenusGranted(recipient, amount);\n }\n\n /**\n * @dev Seize XVS tokens from the specified holders and transfer to recipient\n * @notice Seize XVS rewards allocated to holders\n * @param holders Addresses of the XVS holders\n * @param recipient Address of the XVS token recipient\n * @return The total amount of XVS tokens seized and transferred to recipient\n */\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256) {\n ensureAllowed(\"seizeVenus(address[],address)\");\n\n uint256 holdersLength = holders.length;\n uint256 totalHoldings;\n\n updateAndDistributeRewardsInternal(holders, allMarkets, true, true);\n for (uint256 j; j < holdersLength; ++j) {\n address holder = holders[j];\n uint256 userHolding = venusAccrued[holder];\n\n if (userHolding != 0) {\n totalHoldings += userHolding;\n delete venusAccrued[holder];\n }\n\n emit VenusSeized(holder, userHolding);\n }\n\n if (totalHoldings != 0) {\n IERC20(xvs).safeTransfer(recipient, totalHoldings);\n emit VenusGranted(recipient, totalHoldings);\n }\n\n return totalHoldings;\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @dev The shortfall probe uses the CF path, which reads DeviationBoundedOracle (DBO) bounded prices.\n * When DBO protection mode is active, a holder with a position that is healthy at spot prices may still\n * show a positive shortfall here, and in that case XVS earned will not be granted as collateral even when\n * `collateral` is true. This is consistent with the borrow/redeem CF paths under DBO.\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\n */\n function claimVenus(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) public {\n uint256 holdersLength = holders.length;\n\n updateAndDistributeRewardsInternal(holders, vTokens, borrowers, suppliers);\n for (uint256 j; j < holdersLength; ++j) {\n address holder = holders[j];\n\n // If there is a positive shortfall, the XVS reward is accrued,\n // but won't be granted to this holder\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n holder,\n VToken(address(0)),\n 0,\n 0,\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n\n uint256 value = venusAccrued[holder];\n delete venusAccrued[holder];\n\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\n\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\n if (returnAmount != 0) {\n venusAccrued[holder] = returnAmount;\n }\n }\n }\n\n /**\n * @notice Update and distribute tokens\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function updateAndDistributeRewardsInternal(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers\n ) internal {\n uint256 j;\n uint256 holdersLength = holders.length;\n uint256 vTokensLength = vTokens.length;\n\n for (uint256 i; i < vTokensLength; ++i) {\n VToken vToken = vTokens[i];\n ensureListed(getCorePoolMarket(address(vToken)));\n if (borrowers) {\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n for (j = 0; j < holdersLength; ++j) {\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\n }\n }\n\n if (suppliers) {\n updateVenusSupplyIndex(address(vToken));\n for (j = 0; j < holdersLength; ++j) {\n distributeSupplierVenus(address(vToken), holders[j]);\n }\n }\n }\n }\n\n /**\n * @notice Returns the XVS vToken address\n * @return The address of XVS vToken\n */\n function getXVSVTokenAddress() external view returns (address) {\n return xvsVToken;\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/SetterFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { ComptrollerLensInterface } from \"../../ComptrollerLensInterface.sol\";\nimport { VAIControllerInterface } from \"../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { IPrime } from \"../../../Tokens/Prime/IPrime.sol\";\nimport { ISetterFacet } from \"../interfaces/ISetterFacet.sol\";\nimport { FacetBase } from \"./FacetBase.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\n\n/**\n * @title SetterFacet\n * @author Venus\n * @dev This facet contains all the setters for the states\n * @notice This facet contract contains all the configurational setter functions\n */\ncontract SetterFacet is ISetterFacet, FacetBase {\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor for a market in a pool is changed by admin\n event NewCollateralFactor(\n uint96 indexed poolId,\n VToken indexed vToken,\n uint256 oldCollateralFactorMantissa,\n uint256 newCollateralFactorMantissa\n );\n\n /// @notice Emitted when liquidation incentive for a market in a pool is changed by admin\n event NewLiquidationIncentive(\n uint96 indexed poolId,\n address indexed vToken,\n uint256 oldLiquidationIncentiveMantissa,\n uint256 newLiquidationIncentiveMantissa\n );\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\n\n /// @notice Emitted when deviation bounded oracle is changed\n event NewDeviationBoundedOracle(\n IDeviationBoundedOracle oldDeviationBoundedOracle,\n IDeviationBoundedOracle newDeviationBoundedOracle\n );\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when VAIController is changed\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\n\n /// @notice Emitted when VAI mint rate is changed by admin\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\n\n /// @notice Emitted when protocol state is changed by admin\n event ActionProtocolPaused(bool state);\n\n /// @notice Emitted when treasury guardian is changed\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\n\n /// @notice Emitted when treasury address is changed\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\n\n /// @notice Emitted when treasury percent is changed\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\n\n /// @notice Emitted when liquidator adress is changed\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\n\n /// @notice Emitted when ComptrollerLens address is changed\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\n\n /// @notice Emitted when pause guardian is changed\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\n\n /// @notice Emitted when VAI Vault info is changed\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\n\n /// @notice Emitted when Venus VAI Vault rate is changed\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\n\n /// @notice Emitted when prime token contract address is changed\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for all users in a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\n event IsForcedLiquidationEnabledForUserUpdated(address indexed borrower, address indexed vToken, bool enable);\n\n /// @notice Emitted when XVS token address is changed\n event NewXVSToken(address indexed oldXVS, address indexed newXVS);\n\n /// @notice Emitted when XVS vToken address is changed\n event NewXVSVToken(address indexed oldXVSVToken, address indexed newXVSVToken);\n\n /// @notice Emitted when an account's flash loan whitelist status is updated\n event IsAccountFlashLoanWhitelisted(address indexed account, bool indexed isWhitelisted);\n\n /// @notice Emitted when liquidation threshold for a market in a pool is changed by admin\n event NewLiquidationThreshold(\n uint96 indexed poolId,\n VToken indexed vToken,\n uint256 oldLiquidationThresholdMantissa,\n uint256 newLiquidationThresholdMantissa\n );\n\n /// @notice Emitted when the borrowAllowed flag is updated for a market\n event BorrowAllowedUpdated(uint96 indexed poolId, address indexed market, bool oldStatus, bool newStatus);\n\n /// @notice Emitted when pool active status updated\n event PoolActiveStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\n\n /// @notice Emitted when pool label is updated\n event PoolLabelUpdated(uint96 indexed poolId, string oldLabel, string newLabel);\n\n /// @notice Emitted when pool Fallback status is updated\n event PoolFallbackStatusUpdated(uint96 indexed poolId, bool oldStatus, bool newStatus);\n\n /// @notice Emitted when flash loan pause status changes\n event FlashLoanPauseChanged(bool oldPaused, bool newPaused);\n\n /**\n * @notice Compare two addresses to ensure they are different\n * @param oldAddress The original address to compare\n * @param newAddress The new address to compare\n */\n modifier compareAddress(address oldAddress, address newAddress) {\n require(oldAddress != newAddress, \"old address is same as new address\");\n _;\n }\n\n /**\n * @notice Compare two values to ensure they are different\n * @param oldValue The original value to compare\n * @param newValue The new value to compare\n */\n modifier compareValue(uint256 oldValue, uint256 newValue) {\n require(oldValue != newValue, \"old value is same as new value\");\n _;\n }\n\n /**\n * @notice Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\n * @param newOracle The new price oracle to set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\n return __setPriceOracle(newOracle);\n }\n\n /**\n * @notice Sets a new price oracle for the comptroller\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\n * @param newOracle The new price oracle to set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\n return __setPriceOracle(newOracle);\n }\n\n /**\n * @notice Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\n return __setCloseFactor(newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the closeFactor used when liquidating borrows\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\n return __setCloseFactor(newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Allows the contract admin to set the address of access control of this contract\n * @param newAccessControlAddress New address for the access control\n * @return uint256 0=success, otherwise will revert\n */\n function _setAccessControl(\n address newAccessControlAddress\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newAccessControlAddress);\n\n address oldAccessControlAddress = accessControl;\n\n accessControl = newAccessControlAddress;\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets the collateral factor and liquidation threshold for a market in the Core Pool only.\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256) {\n ensureAllowed(\"setCollateralFactor(address,uint256,uint256)\");\n return __setCollateralFactor(corePoolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\n }\n\n /**\n * @notice Sets the liquidation incentive for a market in the Core Pool only.\n * @param vToken The market to set the liquidationIncentive for\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setLiquidationIncentive(\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n ) external returns (uint256) {\n ensureAllowed(\"setLiquidationIncentive(address,uint256)\");\n return __setLiquidationIncentive(corePoolId, vToken, newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Sets the collateral factor and liquidation threshold for a market in the specified pool.\n * @param poolId The ID of the pool.\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setCollateralFactor(\n uint96 poolId,\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256) {\n ensureAllowed(\"setCollateralFactor(uint96,address,uint256,uint256)\");\n return __setCollateralFactor(poolId, vToken, newCollateralFactorMantissa, newLiquidationThresholdMantissa);\n }\n\n /**\n * @notice Sets the liquidation incentive for a market in the specified pool.\n * @param poolId The ID of the pool.\n * @param vToken The market to set the liquidationIncentive for\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setLiquidationIncentive(\n uint96 poolId,\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n ) external returns (uint256) {\n ensureAllowed(\"setLiquidationIncentive(uint96,address,uint256)\");\n return __setLiquidationIncentive(poolId, vToken, newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Update the address of the liquidator contract\n * @dev Allows the contract admin to update the address of liquidator contract\n * @param newLiquidatorContract_ The new address of the liquidator contract\n */\n function _setLiquidatorContract(\n address newLiquidatorContract_\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newLiquidatorContract_);\n address oldLiquidatorContract = liquidatorContract;\n liquidatorContract = newLiquidatorContract_;\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\n }\n\n /**\n * @notice Admin function to change the Pause Guardian\n * @dev Allows the contract admin to change the Pause Guardian\n * @param newPauseGuardian The address of the new Pause Guardian\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _setPauseGuardian(\n address newPauseGuardian\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(newPauseGuardian);\n\n // Save current value for inclusion in log\n address oldPauseGuardian = pauseGuardian;\n // Store pauseGuardian with value newPauseGuardian\n pauseGuardian = newPauseGuardian;\n\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\n */\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\n }\n\n /**\n * @notice Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\n }\n\n /**\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\n }\n\n /**\n * @notice Set whole protocol pause/unpause state\n * @dev Allows a privileged role to pause/unpause protocol\n * @param state The new state (true=paused, false=unpaused)\n * @return bool The updated state of the protocol\n */\n function _setProtocolPaused(bool state) external returns (bool) {\n ensureAllowed(\"_setProtocolPaused(bool)\");\n\n protocolPaused = state;\n emit ActionProtocolPaused(state);\n return state;\n }\n\n /**\n * @notice Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n __setActionsPaused(markets_, actions_, paused_);\n }\n\n /**\n * @notice Pause/unpause certain actions\n * @dev Allows a privileged role to pause/unpause the protocol action state\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n __setActionsPaused(markets_, actions_, paused_);\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function setActionPausedInternal(address market, Action action, bool paused) internal {\n ensureListed(getCorePoolMarket(market));\n _actionPaused[market][uint256(action)] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @notice Sets a new VAI controller\n * @dev Admin function to set a new VAI controller\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIController(\n VAIControllerInterface vaiController_\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(vaiController_));\n\n VAIControllerInterface oldVaiController = vaiController;\n vaiController = vaiController_;\n emit NewVAIController(oldVaiController, vaiController_);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the VAI mint rate\n * @param newVAIMintRate The new VAI mint rate to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIMintRate(\n uint256 newVAIMintRate\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n uint256 oldVAIMintRate = vaiMintRate;\n vaiMintRate = newVAIMintRate;\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the minted VAI amount of the `owner`\n * @param owner The address of the account to set\n * @param amount The amount of VAI to set to the account\n * @return The number of minted VAI by `owner`\n */\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\n checkProtocolPauseState();\n\n // Pausing is a very serious situation - we revert to sound the alarms\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \"VAI is paused\");\n // Check caller is vaiController\n if (msg.sender != address(vaiController)) {\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\n }\n mintedVAIs[owner] = amount;\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the treasury data.\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\n * @param newTreasuryAddress The new address of the treasury to be set\n * @param newTreasuryPercent The new treasury percent to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256) {\n // Check caller is admin\n ensureAdminOr(treasuryGuardian);\n\n require(newTreasuryPercent < 1e18, \"percent >= 100%\");\n ensureNonzeroAddress(newTreasuryGuardian);\n ensureNonzeroAddress(newTreasuryAddress);\n\n address oldTreasuryGuardian = treasuryGuardian;\n address oldTreasuryAddress = treasuryAddress;\n uint256 oldTreasuryPercent = treasuryPercent;\n\n treasuryGuardian = newTreasuryGuardian;\n treasuryAddress = newTreasuryAddress;\n treasuryPercent = newTreasuryPercent;\n\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\n\n return uint256(Error.NO_ERROR);\n }\n\n /*** Venus Distribution ***/\n\n /**\n * @dev Set ComptrollerLens contract address\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptrollerLens(\n ComptrollerLensInterface comptrollerLens_\n ) external virtual compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the amount of XVS distributed per block to VAI Vault\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\n */\n function _setVenusVAIVaultRate(\n uint256 venusVAIVaultRate_\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\n ensureAdmin();\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\n venusVAIVaultRate = venusVAIVaultRate_;\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\n }\n\n /**\n * @notice Set the VAI Vault infos\n * @param vault_ The address of the VAI Vault\n * @param releaseStartBlock_ The start block of release to VAI Vault\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\n */\n function _setVAIVaultInfo(\n address vault_,\n uint256 releaseStartBlock_,\n uint256 minReleaseAmount_\n ) external compareAddress(vaiVaultAddress, vault_) {\n ensureAdmin();\n ensureNonzeroAddress(vault_);\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n\n vaiVaultAddress = vault_;\n releaseStartBlock = releaseStartBlock_;\n minReleaseAmount = minReleaseAmount_;\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\n }\n\n /**\n * @notice Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\n * @param _prime The new prime token contract to be set\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function setPrimeToken(IPrime _prime) external returns (uint256) {\n return __setPrimeToken(_prime);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime The new prime token contract to be set\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPrimeToken(IPrime _prime) external returns (uint256) {\n return __setPrimeToken(_prime);\n }\n\n /**\n * @notice Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n __setForcedLiquidation(vTokenBorrowed, enable);\n }\n\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\n * borrows in the market may be liquidated regardless of the account liquidity\n * @dev Allows a privileged role to set enable/disable forced liquidations\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n __setForcedLiquidation(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Enables forced liquidations for user's borrows in a certain market. If forced\n * liquidation is enabled, user's borrows in the market may be liquidated regardless of\n * the account liquidity. Forced liquidation may be enabled for a user even if it is not\n * enabled for the entire market.\n * @param borrower The address of the borrower\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external {\n ensureAllowed(\"_setForcedLiquidationForUser(address,address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(getCorePoolMarket(vTokenBorrowed));\n }\n isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledForUserUpdated(borrower, vTokenBorrowed, enable);\n }\n\n /**\n * @notice Set the address of the XVS token\n * @param xvs_ The address of the XVS token\n */\n function _setXVSToken(address xvs_) external {\n ensureAdmin();\n ensureNonzeroAddress(xvs_);\n\n emit NewXVSToken(xvs, xvs_);\n xvs = xvs_;\n }\n\n /**\n * @notice Set the address of the XVS vToken\n * @param xvsVToken_ The address of the XVS vToken\n */\n function _setXVSVToken(address xvsVToken_) external {\n ensureAdmin();\n ensureNonzeroAddress(xvsVToken_);\n\n address underlying = VToken(xvsVToken_).underlying();\n require(underlying == xvs, \"invalid xvs vtoken address\");\n\n emit NewXVSVToken(xvsVToken, xvsVToken_);\n xvsVToken = xvsVToken_;\n }\n\n /**\n * @notice Adds/Removes an account to the flash loan whitelist\n * @param account The account to authorize for flash loans\n * @param isWhiteListed True to whitelist the account for flash loans, false to remove from whitelist\n * @custom:event Emits IsAccountFlashLoanWhitelisted when an account's flash loan whitelist status is updated\n */\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external {\n ensureAllowed(\"setWhiteListFlashLoanAccount(address,bool)\");\n ensureNonzeroAddress(account);\n\n // If the account's status is already the same as the desired status, do nothing\n if (authorizedFlashLoan[account] == isWhiteListed) {\n return;\n }\n\n authorizedFlashLoan[account] = isWhiteListed;\n emit IsAccountFlashLoanWhitelisted(account, isWhiteListed);\n }\n\n /**\n * @notice Pause or unpause flash loans system-wide\n * @param paused True to pause flash loans, false to unpause\n * @custom:access Only Governance\n * @custom:event Emits FlashLoanPauseChanged event\n */\n function setFlashLoanPaused(bool paused) external {\n ensureAllowed(\"setFlashLoanPaused(bool)\");\n\n // Check if value is actually changing\n if (flashLoanPaused == paused) {\n return; // No change needed\n }\n\n emit FlashLoanPauseChanged(flashLoanPaused, paused);\n flashLoanPaused = paused;\n }\n\n /**\n * @notice Updates the label for a specific pool (excluding the Core Pool)\n * @param poolId ID of the pool to update\n * @param newLabel The new label for the pool\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist\n * @custom:error EmptyPoolLabel Reverts if the provided label is an empty string\n * @custom:event PoolLabelUpdated Emitted after the pool label is updated\n */\n function setPoolLabel(uint96 poolId, string calldata newLabel) external {\n ensureAllowed(\"setPoolLabel(uint96,string)\");\n\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n if (bytes(newLabel).length == 0) revert EmptyPoolLabel();\n\n PoolData storage pool = pools[poolId];\n\n if (keccak256(bytes(pool.label)) == keccak256(bytes(newLabel))) {\n return;\n }\n\n emit PoolLabelUpdated(poolId, pool.label, newLabel);\n pool.label = newLabel;\n }\n\n /**\n * @notice updates active status for a specific pool (excluding the Core Pool)\n * @param poolId id of the pool to update\n * @param active true to enable, false to disable\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\n * @custom:event PoolActiveStatusUpdated Emitted after the pool active status is updated.\n */\n function setPoolActive(uint96 poolId, bool active) external {\n ensureAllowed(\"setPoolActive(uint96,bool)\");\n\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n\n PoolData storage pool = pools[poolId];\n\n if (pool.isActive == active) {\n return;\n }\n\n emit PoolActiveStatusUpdated(poolId, pool.isActive, active);\n pool.isActive = active;\n }\n\n /**\n * @notice Updates the `allowCorePoolFallback` flag for a specific pool (excluding the Core Pool).\n * @param poolId ID of the pool to update.\n * @param allowFallback True to allow fallback to Core Pool, false to disable.\n * @custom:error InvalidOperationForCorePool Reverts when attempting to call pool-specific methods on the Core Pool.\n * @custom:error PoolDoesNotExist Reverts if the target pool ID does not exist.\n * @custom:event PoolFallbackStatusUpdated Emitted after the pool fallback flag is updated.\n */\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external {\n ensureAllowed(\"setAllowCorePoolFallback(uint96,bool)\");\n\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n if (poolId == corePoolId) revert InvalidOperationForCorePool();\n\n PoolData storage pool = pools[poolId];\n\n if (pool.allowCorePoolFallback == allowFallback) {\n return;\n }\n\n emit PoolFallbackStatusUpdated(poolId, pool.allowCorePoolFallback, allowFallback);\n pool.allowCorePoolFallback = allowFallback;\n }\n\n /**\n * @notice Updates the `isBorrowAllowed` flag for a market in a pool.\n * @param poolId The ID of the pool.\n * @param vToken The address of the market (vToken).\n * @param borrowAllowed The new borrow allowed status.\n * @custom:error PoolDoesNotExist Reverts if the pool ID is invalid.\n * @custom:error MarketConfigNotFound Reverts if the market is not listed in the pool.\n * @custom:event BorrowAllowedUpdated Emitted after the borrow permission for a market is updated.\n */\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external {\n ensureAllowed(\"setIsBorrowAllowed(uint96,address,bool)\");\n\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n\n PoolMarketId index = getPoolMarketIndex(poolId, vToken);\n Market storage m = _poolMarkets[index];\n\n if (!m.isListed) {\n revert MarketConfigNotFound();\n }\n\n if (m.isBorrowAllowed == borrowAllowed) {\n return;\n }\n\n emit BorrowAllowedUpdated(poolId, vToken, m.isBorrowAllowed, borrowAllowed);\n m.isBorrowAllowed = borrowAllowed;\n }\n\n /**\n * @notice Sets the DeviationBoundedOracle for conservative CF-path pricing\n * @param newDeviationBoundedOracle The new DeviationBoundedOracle contract\n * @return uint256 0=success, otherwise a failure\n */\n function setDeviationBoundedOracle(\n IDeviationBoundedOracle newDeviationBoundedOracle\n ) external compareAddress(address(deviationBoundedOracle), address(newDeviationBoundedOracle)) returns (uint256) {\n ensureAllowed(\"setDeviationBoundedOracle(address)\");\n\n ensureNonzeroAddress(address(newDeviationBoundedOracle));\n\n IDeviationBoundedOracle oldDeviationBoundedOracle = deviationBoundedOracle;\n deviationBoundedOracle = newDeviationBoundedOracle;\n\n emit NewDeviationBoundedOracle(oldDeviationBoundedOracle, newDeviationBoundedOracle);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle\n * @param newOracle The new price oracle to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setPriceOracle(\n ResilientOracleInterface newOracle\n ) internal compareAddress(address(oracle), address(newOracle)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(newOracle));\n\n // Track the old oracle for the comptroller\n ResilientOracleInterface oldOracle = oracle;\n\n // Set comptroller's oracle to newOracle\n oracle = newOracle;\n\n // Emit NewPriceOracle(oldOracle, newOracle)\n emit NewPriceOracle(oldOracle, newOracle);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the close factor. Used by _setCloseFactor and setCloseFactor\n * @param newCloseFactorMantissa The new close factor to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setCloseFactor(\n uint256 newCloseFactorMantissa\n ) internal compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\n\n //-- Check close factor <= 0.9\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\n //-- Check close factor >= 0.05\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\n\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\n }\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the collateral factor and the liquidation threshold. Used by setCollateralFactor\n * @param poolId The ID of the pool.\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor to be set\n * @param newLiquidationThresholdMantissa The new liquidation threshold to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setCollateralFactor(\n uint96 poolId,\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) internal returns (uint256) {\n ensureNonzeroAddress(address(vToken));\n\n // Check if pool exists\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n\n // Verify market is listed in the pool\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, address(vToken))];\n ensureListed(market);\n\n //-- Check collateral factor <= 1\n if (newCollateralFactorMantissa > mantissaOne) {\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\n }\n\n // Ensure that liquidation threshold <= 1\n if (newLiquidationThresholdMantissa > mantissaOne) {\n return fail(Error.INVALID_LIQUIDATION_THRESHOLD, FailureInfo.SET_LIQUIDATION_THRESHOLD_VALIDATION);\n }\n\n // Ensure that liquidation threshold >= CF\n if (newLiquidationThresholdMantissa < newCollateralFactorMantissa) {\n return\n fail(\n Error.INVALID_LIQUIDATION_THRESHOLD,\n FailureInfo.COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\n );\n }\n\n // Set market's collateral factor to new collateral factor, remember old value\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n if (newCollateralFactorMantissa != oldCollateralFactorMantissa) {\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n\n // Emit event with poolId, asset, old collateral factor, and new collateral factor\n emit NewCollateralFactor(poolId, vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n }\n\n uint256 oldLiquidationThresholdMantissa = market.liquidationThresholdMantissa;\n if (newLiquidationThresholdMantissa != oldLiquidationThresholdMantissa) {\n market.liquidationThresholdMantissa = newLiquidationThresholdMantissa;\n\n emit NewLiquidationThreshold(\n poolId,\n vToken,\n oldLiquidationThresholdMantissa,\n newLiquidationThresholdMantissa\n );\n }\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the liquidation incentive. Used by setLiquidationIncentive\n * @param poolId The ID of the pool.\n * @param vToken The market to set the Incentive for\n * @param newLiquidationIncentiveMantissa The new liquidation incentive to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setLiquidationIncentive(\n uint96 poolId,\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n )\n internal\n compareValue(\n _poolMarkets[getPoolMarketIndex(poolId, vToken)].liquidationIncentiveMantissa,\n newLiquidationIncentiveMantissa\n )\n returns (uint256)\n {\n // Check if pool exists\n if (poolId > lastPoolId) revert PoolDoesNotExist(poolId);\n\n // Verify market is listed in the pool\n Market storage market = _poolMarkets[getPoolMarketIndex(poolId, vToken)];\n ensureListed(market);\n\n require(newLiquidationIncentiveMantissa >= mantissaOne, \"incentive < 1e18\");\n\n emit NewLiquidationIncentive(\n poolId,\n vToken,\n market.liquidationIncentiveMantissa,\n newLiquidationIncentiveMantissa\n );\n\n // Set liquidation incentive to new incentive\n market.liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the borrow caps. Used by _setMarketBorrowCaps and setMarketBorrowCaps\n * @param vTokens The markets to set the borrow caps on\n * @param newBorrowCaps The new borrow caps to be set\n */\n function __setMarketBorrowCaps(VToken[] memory vTokens, uint256[] memory newBorrowCaps) internal {\n ensureAllowed(\"_setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @dev Updates the supply caps. Used by _setMarketSupplyCaps and setMarketSupplyCaps\n * @param vTokens The markets to set the supply caps on\n * @param newSupplyCaps The new supply caps to be set\n */\n function __setMarketSupplyCaps(VToken[] memory vTokens, uint256[] memory newSupplyCaps) internal {\n ensureAllowed(\"_setMarketSupplyCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numSupplyCaps = newSupplyCaps.length;\n\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @dev Updates the prime token. Used by _setPrimeToken and setPrimeToken\n * @param _prime The new prime token to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setPrimeToken(IPrime _prime) internal returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(_prime));\n\n IPrime oldPrime = prime;\n prime = _prime;\n emit NewPrimeToken(oldPrime, _prime);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the forced liquidation. Used by _setForcedLiquidation and setForcedLiquidation\n * @param vTokenBorrowed The market to set the forced liquidation on\n * @param enable Whether to enable forced liquidations\n */\n function __setForcedLiquidation(address vTokenBorrowed, bool enable) internal {\n ensureAllowed(\"_setForcedLiquidation(address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(getCorePoolMarket(vTokenBorrowed));\n }\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @dev Updates the actions paused. Used by _setActionsPaused and setActionsPaused\n * @param markets_ The markets to set the actions paused on\n * @param actions_ The actions to set the paused state on\n * @param paused_ The new paused state to be set\n */\n function __setActionsPaused(address[] memory markets_, Action[] memory actions_, bool paused_) internal {\n ensureAllowed(\"_setActionsPaused(address[],uint8[],bool)\");\n\n uint256 numMarkets = markets_.length;\n uint256 numActions = actions_.length;\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/Diamond/facets/XVSRewardsHelper.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { FacetBase } from \"./FacetBase.sol\";\n\n/**\n * @title XVSRewardsHelper\n * @author Venus\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\n */\ncontract XVSRewardsHelper is FacetBase {\n /// @notice Emitted when XVS is distributed to a borrower\n event DistributedBorrowerVenus(\n VToken indexed vToken,\n address indexed borrower,\n uint256 venusDelta,\n uint256 venusBorrowIndex\n );\n\n /// @notice Emitted when XVS is distributed to a supplier\n event DistributedSupplierVenus(\n VToken indexed vToken,\n address indexed supplier,\n uint256 venusDelta,\n uint256 venusSupplyIndex\n );\n\n /**\n * @notice Accrue XVS to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n */\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\n if (deltaBlocks != 0 && borrowSpeed != 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \"224\");\n borrowState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n borrowState.block = blockNumber;\n }\n }\n\n /**\n * @notice Accrue XVS to the market by updating the supply index\n * @param vToken The market whose supply index to update\n */\n function updateVenusSupplyIndex(address vToken) internal {\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n uint256 supplySpeed = venusSupplySpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\n if (deltaBlocks != 0 && supplySpeed != 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \"224\");\n supplyState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n supplyState.block = blockNumber;\n }\n }\n\n /**\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute XVS to\n */\n function distributeSupplierVenus(address vToken, address supplier) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 supplyIndex = venusSupplyState[vToken].index;\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\n // Update supplier's index to the current index since we are distributing accrued XVS\n venusSupplierIndex[vToken][supplier] = supplyIndex;\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n // Multiply of supplierTokens and supplierDelta\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\n // Addition of supplierAccrued and supplierDelta\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\n }\n\n /**\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute XVS to\n */\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 borrowIndex = venusBorrowState[vToken].index;\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\n // Update borrowers's index to the current index since we are distributing accrued XVS\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\n }\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n function diamondCut(FacetCut[] calldata _diamondCut) external;\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IFacetBase.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { Action } from \"../../../Comptroller/ComptrollerInterface.sol\";\nimport { PoolMarketId } from \"../../../Comptroller/Types/PoolMarketId.sol\";\n\nenum WeightFunction {\n /// @notice Use the collateral factor of the asset for weighting\n USE_COLLATERAL_FACTOR,\n /// @notice Use the liquidation threshold of the asset for weighting\n USE_LIQUIDATION_THRESHOLD\n}\n\ninterface IFacetBase {\n /**\n * @notice The initial XVS rewards index for a market\n */\n function venusInitialIndex() external pure returns (uint224);\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param action Action id\n * @param market vToken address\n */\n function actionPaused(address market, Action action) external view returns (bool);\n\n /**\n * @notice Returns the XVS address\n * @return The address of XVS token\n */\n function getXVSAddress() external view returns (address);\n\n function getPoolMarketIndex(uint96 poolId, address vToken) external pure returns (PoolMarketId);\n\n function corePoolId() external pure returns (uint96);\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IFlashLoanFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\n\ninterface IFlashLoanFacet {\n /// @notice Data structure to hold flash loan related data during execution\n struct FlashLoanFee {\n uint256[] totalFees;\n uint256[] protocolFees;\n }\n\n function executeFlashLoan(\n address payable onBehalf,\n address payable receiver,\n VToken[] memory vTokens,\n uint256[] memory underlyingAmounts,\n bytes memory param\n ) external;\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IMarketFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { WeightFunction } from \"./IFacetBase.sol\";\n\ninterface IMarketFacet {\n function isComptroller() external pure returns (bool);\n\n function liquidateCalculateSeizeTokens(\n address borrower,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function checkMembership(address account, VToken vToken) external view returns (bool);\n\n function enterMarketBehalf(address onBehalf, address vToken) external returns (uint256);\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n function _supportMarket(VToken vToken) external returns (uint256);\n\n function supportMarket(VToken vToken) external returns (uint256);\n\n function isMarketListed(VToken vToken) external view returns (bool);\n\n function getAssetsIn(address account) external view returns (VToken[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function updateDelegate(address delegate, bool allowBorrows) external;\n\n function unlistMarket(address market) external returns (uint256);\n\n function createPool(string memory label) external returns (uint96);\n\n function enterPool(uint96 poolId) external;\n\n function addPoolMarkets(uint96[] calldata poolIds, address[] calldata vTokens) external;\n\n function removePoolMarket(uint96 poolId, address vToken) external;\n\n function markets(\n address vToken\n )\n external\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n );\n\n function poolMarkets(\n uint96 poolId,\n address vToken\n )\n external\n view\n returns (\n bool isListed,\n uint256 collateralFactorMantissa,\n bool isVenus,\n uint256 liquidationThresholdMantissa,\n uint256 liquidationIncentiveMantissa,\n uint96 marketPoolId,\n bool isBorrowAllowed\n );\n\n function hasValidPoolBorrows(address user, uint96 targetPoolId) external view returns (bool);\n\n function getCollateralFactor(address vToken) external view returns (uint256);\n\n function getLiquidationThreshold(address vToken) external view returns (uint256);\n\n function getLiquidationIncentive(address vToken) external view returns (uint256);\n\n function getEffectiveLtvFactor(\n address account,\n address vToken,\n WeightFunction weightingStrategy\n ) external view returns (uint256);\n\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\n\n function getPoolVTokens(uint96 poolId) external view returns (address[] memory);\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IPolicyFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\n\ninterface IPolicyFacet {\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\n\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\n\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\n\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount\n ) external returns (uint256);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount,\n uint256 borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount,\n uint256 seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external returns (uint256);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external;\n\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256);\n\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\n\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256);\n\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external;\n\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall);\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/IRewardFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { IFacetBase } from \"./IFacetBase.sol\";\n\ninterface IRewardFacet is IFacetBase {\n function claimVenus(address holder) external;\n\n function claimVenus(address holder, VToken[] calldata vTokens) external;\n\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\n\n function claimVenusAsCollateral(address holder) external;\n\n function _grantXVS(address recipient, uint256 amount) external;\n\n function getXVSVTokenAddress() external view returns (address);\n\n function claimVenus(\n address[] calldata holders,\n VToken[] calldata vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) external;\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256);\n}\n" + }, + "contracts/Comptroller/Diamond/interfaces/ISetterFacet.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\nimport { VToken } from \"../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterface.sol\";\nimport { VAIControllerInterface } from \"../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterface } from \"../../../Comptroller/ComptrollerLensInterface.sol\";\nimport { IPrime } from \"../../../Tokens/Prime/IPrime.sol\";\n\ninterface ISetterFacet {\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\n\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\n\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\n\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256);\n\n function setCollateralFactor(\n uint96 poolId,\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256);\n\n function setLiquidationIncentive(\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n ) external returns (uint256);\n\n function setLiquidationIncentive(\n uint96 poolId,\n address vToken,\n uint256 newLiquidationIncentiveMantissa\n ) external returns (uint256);\n\n function _setLiquidatorContract(address newLiquidatorContract_) external;\n\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\n\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setProtocolPaused(bool state) external returns (bool);\n\n function setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\n\n function _setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\n\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\n\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\n\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\n\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256);\n\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external returns (uint256);\n\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\n\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\n\n function _setForcedLiquidation(address vToken, bool enable) external;\n\n function setPrimeToken(IPrime _prime) external returns (uint256);\n\n function _setPrimeToken(IPrime _prime) external returns (uint);\n\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external;\n\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external;\n\n function _setXVSToken(address xvs_) external;\n\n function _setXVSVToken(address xvsVToken_) external;\n\n function setWhiteListFlashLoanAccount(address account, bool isWhiteListed) external;\n\n function setIsBorrowAllowed(uint96 poolId, address vToken, bool borrowAllowed) external;\n\n function setPoolActive(uint96 poolId, bool active) external;\n\n function setPoolLabel(uint96 poolId, string calldata newLabel) external;\n\n function setAllowCorePoolFallback(uint96 poolId, bool allowFallback) external;\n\n function setFlashLoanPaused(bool paused) external;\n\n function setDeviationBoundedOracle(IDeviationBoundedOracle newDeviationBoundedOracle) external returns (uint256);\n}\n" + }, + "contracts/Comptroller/legacy/ComptrollerInterfaceR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"../../Tokens/VTokens/VToken.sol\";\nimport { VAIControllerInterface } from \"../../Tokens/VAI/VAIControllerInterface.sol\";\n\nenum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n}\n\ninterface ComptrollerInterfaceR1 {\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() external pure returns (bool);\n\n /*** Assets You Are In ***/\n\n function enterMarkets(address[] calldata vTokens) external returns (uint[] memory);\n\n function exitMarket(address vToken) external returns (uint);\n\n /*** Policy Hooks ***/\n\n function mintAllowed(address vToken, address minter, uint mintAmount) external returns (uint);\n\n function mintVerify(address vToken, address minter, uint mintAmount, uint mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint redeemTokens) external returns (uint);\n\n function redeemVerify(address vToken, address redeemer, uint redeemAmount, uint redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint borrowAmount) external returns (uint);\n\n function borrowVerify(address vToken, address borrower, uint borrowAmount) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint repayAmount,\n uint borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount\n ) external returns (uint);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint repayAmount,\n uint seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external returns (uint);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external;\n\n function transferAllowed(address vToken, address src, address dst, uint transferTokens) external returns (uint);\n\n function transferVerify(address vToken, address src, address dst, uint transferTokens) external;\n\n /*** Liquidity/Liquidation Calculations ***/\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function setMintedVAIOf(address owner, uint amount) external returns (uint);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint repayAmount\n ) external view returns (uint, uint);\n\n function getXVSAddress() external view returns (address);\n\n function markets(address) external view returns (bool, uint);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function getAccountLiquidity(address) external view returns (uint, uint, uint);\n\n function getAssetsIn(address) external view returns (VToken[] memory);\n\n function claimVenus(address) external;\n\n function venusAccrued(address) external view returns (uint);\n\n function venusSupplySpeeds(address) external view returns (uint);\n\n function venusBorrowSpeeds(address) external view returns (uint);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function venusSupplierIndex(address, address) external view returns (uint);\n\n function venusInitialIndex() external view returns (uint224);\n\n function venusBorrowerIndex(address, address) external view returns (uint);\n\n function venusBorrowState(address) external view returns (uint224, uint32);\n\n function venusSupplyState(address) external view returns (uint224, uint32);\n\n function approvedDelegates(address borrower, address delegate) external view returns (bool);\n\n function vaiController() external view returns (VAIControllerInterface);\n\n function liquidationIncentiveMantissa() external view returns (uint);\n\n function protocolPaused() external view returns (bool);\n\n function actionPaused(address market, Action action) external view returns (bool);\n\n function mintedVAIs(address user) external view returns (uint);\n\n function vaiMintRate() external view returns (uint);\n}\n\ninterface IVAIVault {\n function updatePendingRewards() external;\n}\n\ninterface IComptroller {\n function liquidationIncentiveMantissa() external view returns (uint);\n\n /*** Treasury Data ***/\n function treasuryAddress() external view returns (address);\n\n function treasuryPercent() external view returns (uint);\n}\n" + }, + "contracts/Comptroller/legacy/ComptrollerLensInterfaceR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../Tokens/VTokens/VToken.sol\";\n\ninterface ComptrollerLensInterfaceR1 {\n function liquidateCalculateSeizeTokens(\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function liquidateVAICalculateSeizeTokens(\n address comptroller,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint);\n\n function getHypotheticalAccountLiquidity(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount\n ) external view returns (uint, uint, uint);\n}\n" + }, + "contracts/Comptroller/legacy/ComptrollerStorageR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"../../Tokens/VTokens/VToken.sol\";\nimport { VAIControllerInterface } from \"../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterfaceR1 } from \"./ComptrollerLensInterfaceR1.sol\";\nimport { IPrime } from \"../../Tokens/Prime/IPrime.sol\";\n\ncontract UnitrollerAdminStorageR1 {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of Unitroller\n */\n address public comptrollerImplementation;\n\n /**\n * @notice Pending brains of Unitroller\n */\n address public pendingComptrollerImplementation;\n}\n\ncontract ComptrollerV1StorageR1 is UnitrollerAdminStorageR1 {\n /**\n * @notice Oracle which gives the price of any given asset\n */\n ResilientOracleInterface public oracle;\n\n /**\n * @notice Multiplier used to calculate the maximum repayAmount when liquidating a borrow\n */\n uint256 public closeFactorMantissa;\n\n /**\n * @notice Multiplier representing the discount on collateral that a liquidator receives\n */\n uint256 public liquidationIncentiveMantissa;\n\n /**\n * @notice Max number of assets a single account can participate in (borrow or use as collateral)\n */\n uint256 public maxAssets;\n\n /**\n * @notice Per-account mapping of \"assets you are in\", capped by maxAssets\n */\n mapping(address => VToken[]) public accountAssets;\n\n struct Market {\n /// @notice Whether or not this market is listed\n bool isListed;\n /**\n * @notice Multiplier representing the most one can borrow against their collateral in this market.\n * For instance, 0.9 to allow borrowing 90% of collateral value.\n * Must be between 0 and 1, and stored as a mantissa.\n */\n uint256 collateralFactorMantissa;\n /// @notice Per-market mapping of \"accounts in this asset\"\n mapping(address => bool) accountMembership;\n /// @notice Whether or not this market receives XVS\n bool isVenus;\n }\n\n /**\n * @notice Official mapping of vTokens -> Market metadata\n * @dev Used e.g. to determine if a market is supported\n */\n mapping(address => Market) public markets;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n address public pauseGuardian;\n\n /// @notice Whether minting is paused (deprecated, superseded by actionPaused)\n bool private _mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool private _borrowGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal transferGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n bool internal seizeGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal mintGuardianPaused;\n /// @notice Whether borrowing is paused (deprecated, superseded by actionPaused)\n mapping(address => bool) internal borrowGuardianPaused;\n\n struct VenusMarketState {\n /// @notice The market's last updated venusBorrowIndex or venusSupplyIndex\n uint224 index;\n /// @notice The block number the index was last updated at\n uint32 block;\n }\n\n /// @notice A list of all markets\n VToken[] public allMarkets;\n\n /// @notice The rate at which the flywheel distributes XVS, per block\n uint256 internal venusRate;\n\n /// @notice The portion of venusRate that each market currently receives\n mapping(address => uint256) internal venusSpeeds;\n\n /// @notice The Venus market supply state for each market\n mapping(address => VenusMarketState) public venusSupplyState;\n\n /// @notice The Venus market borrow state for each market\n mapping(address => VenusMarketState) public venusBorrowState;\n\n /// @notice The Venus supply index for each market for each supplier as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusSupplierIndex;\n\n /// @notice The Venus borrow index for each market for each borrower as of the last time they accrued XVS\n mapping(address => mapping(address => uint256)) public venusBorrowerIndex;\n\n /// @notice The XVS accrued but not yet transferred to each user\n mapping(address => uint256) public venusAccrued;\n\n /// @notice The Address of VAIController\n VAIControllerInterface public vaiController;\n\n /// @notice The minted VAI amount to each user\n mapping(address => uint256) public mintedVAIs;\n\n /// @notice VAI Mint Rate as a percentage\n uint256 public vaiMintRate;\n\n /**\n * @notice The Pause Guardian can pause certain actions as a safety mechanism.\n */\n bool public mintVAIGuardianPaused;\n bool public repayVAIGuardianPaused;\n\n /**\n * @notice Pause/Unpause whole protocol actions\n */\n bool public protocolPaused;\n\n /// @notice The rate at which the flywheel distributes XVS to VAI Minters, per block (deprecated)\n uint256 private venusVAIRate;\n}\n\ncontract ComptrollerV2StorageR1 is ComptrollerV1StorageR1 {\n /// @notice The rate at which the flywheel distributes XVS to VAI Vault, per block\n uint256 public venusVAIVaultRate;\n\n // address of VAI Vault\n address public vaiVaultAddress;\n\n // start block of release to VAI Vault\n uint256 public releaseStartBlock;\n\n // minimum release amount to VAI Vault\n uint256 public minReleaseAmount;\n}\n\ncontract ComptrollerV3StorageR1 is ComptrollerV2StorageR1 {\n /// @notice The borrowCapGuardian can set borrowCaps to any number for any market. Lowering the borrow cap could disable borrowing on the given market.\n address public borrowCapGuardian;\n\n /// @notice Borrow caps enforced by borrowAllowed for each vToken address.\n mapping(address => uint256) public borrowCaps;\n}\n\ncontract ComptrollerV4StorageR1 is ComptrollerV3StorageR1 {\n /// @notice Treasury Guardian address\n address public treasuryGuardian;\n\n /// @notice Treasury address\n address public treasuryAddress;\n\n /// @notice Fee percent of accrued interest with decimal 18\n uint256 public treasuryPercent;\n}\n\ncontract ComptrollerV5StorageR1 is ComptrollerV4StorageR1 {\n /// @notice The portion of XVS that each contributor receives per block (deprecated)\n mapping(address => uint256) private venusContributorSpeeds;\n\n /// @notice Last block at which a contributor's XVS rewards have been allocated (deprecated)\n mapping(address => uint256) private lastContributorBlock;\n}\n\ncontract ComptrollerV6StorageR1 is ComptrollerV5StorageR1 {\n address public liquidatorContract;\n}\n\ncontract ComptrollerV7StorageR1 is ComptrollerV6StorageR1 {\n ComptrollerLensInterfaceR1 public comptrollerLens;\n}\n\ncontract ComptrollerV8StorageR1 is ComptrollerV7StorageR1 {\n /// @notice Supply caps enforced by mintAllowed for each vToken address. Defaults to zero which corresponds to minting notAllowed\n mapping(address => uint256) public supplyCaps;\n}\n\ncontract ComptrollerV9StorageR1 is ComptrollerV8StorageR1 {\n /// @notice AccessControlManager address\n address internal accessControl;\n\n /// @notice True if a certain action is paused on a certain market\n mapping(address => mapping(uint256 => bool)) internal _actionPaused;\n}\n\ncontract ComptrollerV10StorageR1 is ComptrollerV9StorageR1 {\n /// @notice The rate at which venus is distributed to the corresponding borrow market (per block)\n mapping(address => uint256) public venusBorrowSpeeds;\n\n /// @notice The rate at which venus is distributed to the corresponding supply market (per block)\n mapping(address => uint256) public venusSupplySpeeds;\n}\n\ncontract ComptrollerV11StorageR1 is ComptrollerV10StorageR1 {\n /// @notice Whether the delegate is allowed to borrow or redeem on behalf of the user\n //mapping(address user => mapping (address delegate => bool approved)) public approvedDelegates;\n mapping(address => mapping(address => bool)) public approvedDelegates;\n}\n\ncontract ComptrollerV12StorageR1 is ComptrollerV11StorageR1 {\n /// @notice Whether forced liquidation is enabled for all users borrowing in a certain market\n mapping(address => bool) public isForcedLiquidationEnabled;\n}\n\ncontract ComptrollerV13StorageR1 is ComptrollerV12StorageR1 {\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in _facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in _facetAddresses array\n }\n\n mapping(bytes4 => FacetAddressAndPosition) internal _selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) internal _facetFunctionSelectors;\n // facet addresses\n address[] internal _facetAddresses;\n}\n\ncontract ComptrollerV14StorageR1 is ComptrollerV13StorageR1 {\n /// @notice Prime token address\n IPrime public prime;\n}\n\ncontract ComptrollerV15StorageR1 is ComptrollerV14StorageR1 {\n /// @notice Whether forced liquidation is enabled for the borrows of a user in a market\n mapping(address user => mapping(address market => bool)) public isForcedLiquidationEnabledForUser;\n}\n\ncontract ComptrollerV16StorageR1 is ComptrollerV15StorageR1 {\n /// @notice The XVS token contract address\n address internal xvs;\n\n /// @notice The XVS vToken contract address\n address internal xvsVToken;\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/DiamondConsolidatedR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { MarketFacetR1 } from \"./facets/MarketFacetR1.sol\";\nimport { PolicyFacetR1 } from \"./facets/PolicyFacetR1.sol\";\nimport { RewardFacetR1 } from \"./facets/RewardFacetR1.sol\";\nimport { SetterFacetR1 } from \"./facets/SetterFacetR1.sol\";\nimport { DiamondR1 } from \"./DiamondR1.sol\";\n\n/**\n * @title DiamondConsolidated\n * @author Venus\n * @notice This contract contains the functions defined in the different facets of the Diamond, plus the getters to the public variables.\n * This contract cannot be deployed, due to its size. Its main purpose is to allow the easy generation of an ABI and the typechain to interact with the\n * Unitroller contract in a simple way\n */\ncontract DiamondConsolidatedR1 is DiamondR1, MarketFacetR1, PolicyFacetR1, RewardFacetR1, SetterFacetR1 {}\n" + }, + "contracts/Comptroller/legacy/Diamond/DiamondR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IDiamondCutR1 } from \"./interfaces/IDiamondCutR1.sol\";\nimport { Unitroller } from \"../../Unitroller.sol\";\nimport { ComptrollerV16StorageR1 } from \"../ComptrollerStorageR1.sol\";\n\n/**\n * @title Diamond\n * @author Venus\n * @notice This contract contains functions related to facets\n */\ncontract DiamondR1 is IDiamondCutR1, ComptrollerV16StorageR1 {\n /// @notice Emitted when functions are added, replaced or removed to facets\n event DiamondCut(IDiamondCutR1.FacetCut[] _diamondCut);\n\n struct Facet {\n address facetAddress;\n bytes4[] functionSelectors;\n }\n\n /**\n * @notice Call _acceptImplementation to accept the diamond proxy as new implementaion\n * @param unitroller Address of the unitroller\n */\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n /**\n * @notice To add function selectors to the facet's mapping\n * @dev Allows the contract admin to add function selectors\n * @param diamondCut_ IDiamondCutR1 contains facets address, action and function selectors\n */\n function diamondCut(IDiamondCutR1.FacetCut[] memory diamondCut_) public {\n require(msg.sender == admin, \"only unitroller admin can\");\n libDiamondCut(diamondCut_);\n }\n\n /**\n * @notice Get all function selectors mapped to the facet address\n * @param facet Address of the facet\n * @return selectors Array of function selectors\n */\n function facetFunctionSelectors(address facet) external view returns (bytes4[] memory) {\n return _facetFunctionSelectors[facet].functionSelectors;\n }\n\n /**\n * @notice Get facet position in the _facetFunctionSelectors through facet address\n * @param facet Address of the facet\n * @return Position of the facet\n */\n function facetPosition(address facet) external view returns (uint256) {\n return _facetFunctionSelectors[facet].facetAddressPosition;\n }\n\n /**\n * @notice Get all facet addresses\n * @return facetAddresses Array of facet addresses\n */\n function facetAddresses() external view returns (address[] memory) {\n return _facetAddresses;\n }\n\n /**\n * @notice Get facet address and position through function selector\n * @param functionSelector function selector\n * @return FacetAddressAndPosition facet address and position\n */\n function facetAddress(\n bytes4 functionSelector\n ) external view returns (ComptrollerV16StorageR1.FacetAddressAndPosition memory) {\n return _selectorToFacetAndPosition[functionSelector];\n }\n\n /**\n * @notice Get all facets address and their function selector\n * @return facets_ Array of Facet\n */\n function facets() external view returns (Facet[] memory) {\n uint256 facetsLength = _facetAddresses.length;\n Facet[] memory facets_ = new Facet[](facetsLength);\n for (uint256 i; i < facetsLength; ++i) {\n address facet = _facetAddresses[i];\n facets_[i].facetAddress = facet;\n facets_[i].functionSelectors = _facetFunctionSelectors[facet].functionSelectors;\n }\n return facets_;\n }\n\n /**\n * @notice To add function selectors to the facets' mapping\n * @param diamondCut_ IDiamondCutR1 contains facets address, action and function selectors\n */\n function libDiamondCut(IDiamondCutR1.FacetCut[] memory diamondCut_) internal {\n uint256 diamondCutLength = diamondCut_.length;\n for (uint256 facetIndex; facetIndex < diamondCutLength; ++facetIndex) {\n IDiamondCutR1.FacetCutAction action = diamondCut_[facetIndex].action;\n if (action == IDiamondCutR1.FacetCutAction.Add) {\n addFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCutR1.FacetCutAction.Replace) {\n replaceFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else if (action == IDiamondCutR1.FacetCutAction.Remove) {\n removeFunctions(diamondCut_[facetIndex].facetAddress, diamondCut_[facetIndex].functionSelectors);\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n }\n emit DiamondCut(diamondCut_);\n }\n\n /**\n * @notice Add function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to add in the mapping\n */\n function addFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress == address(0), \"LibDiamondCut: Can't add function that already exists\");\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Replace facet's address mapping for function selectors i.e selectors already associate to any other existing facet\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to replace in the mapping\n */\n function replaceFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n require(functionSelectors.length != 0, \"LibDiamondCut: No selectors in facet to cut\");\n require(facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(_facetFunctionSelectors[facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(facetAddress);\n }\n uint256 functionSelectorsLength = functionSelectors.length;\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress != facetAddress, \"LibDiamondCut: Can't replace function with same function\");\n removeFunction(oldFacetAddress, selector);\n addFunction(selector, selectorPosition, facetAddress);\n ++selectorPosition;\n }\n }\n\n /**\n * @notice Remove function selectors to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param functionSelectors Array of function selectors need to remove in the mapping\n */\n function removeFunctions(address facetAddress, bytes4[] memory functionSelectors) internal {\n uint256 functionSelectorsLength = functionSelectors.length;\n require(functionSelectorsLength != 0, \"LibDiamondCut: No selectors in facet to cut\");\n // if function does not exist then do nothing and revert\n require(facetAddress == address(0), \"LibDiamondCut: Remove facet address must be address(0)\");\n for (uint256 selectorIndex; selectorIndex < functionSelectorsLength; ++selectorIndex) {\n bytes4 selector = functionSelectors[selectorIndex];\n address oldFacetAddress = _selectorToFacetAndPosition[selector].facetAddress;\n removeFunction(oldFacetAddress, selector);\n }\n }\n\n /**\n * @notice Add new facet to the proxy\n * @param facetAddress Address of the facet\n */\n function addFacet(address facetAddress) internal {\n enforceHasContractCode(facetAddress, \"Diamond: New facet has no code\");\n _facetFunctionSelectors[facetAddress].facetAddressPosition = _facetAddresses.length;\n _facetAddresses.push(facetAddress);\n }\n\n /**\n * @notice Add function selector to the facet's address mapping\n * @param selector funciton selector need to be added\n * @param selectorPosition funciton selector position\n * @param facetAddress Address of the facet\n */\n function addFunction(bytes4 selector, uint96 selectorPosition, address facetAddress) internal {\n _selectorToFacetAndPosition[selector].functionSelectorPosition = selectorPosition;\n _facetFunctionSelectors[facetAddress].functionSelectors.push(selector);\n _selectorToFacetAndPosition[selector].facetAddress = facetAddress;\n }\n\n /**\n * @notice Remove function selector to the facet's address mapping\n * @param facetAddress Address of the facet\n * @param selector function selectors need to remove in the mapping\n */\n function removeFunction(address facetAddress, bytes4 selector) internal {\n require(facetAddress != address(0), \"LibDiamondCut: Can't remove function that doesn't exist\");\n\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = _selectorToFacetAndPosition[selector].functionSelectorPosition;\n uint256 lastSelectorPosition = _facetFunctionSelectors[facetAddress].functionSelectors.length - 1;\n // if not the same then replace selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = _facetFunctionSelectors[facetAddress].functionSelectors[lastSelectorPosition];\n _facetFunctionSelectors[facetAddress].functionSelectors[selectorPosition] = lastSelector;\n _selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n _facetFunctionSelectors[facetAddress].functionSelectors.pop();\n delete _selectorToFacetAndPosition[selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = _facetAddresses.length - 1;\n uint256 facetAddressPosition = _facetFunctionSelectors[facetAddress].facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = _facetAddresses[lastFacetAddressPosition];\n _facetAddresses[facetAddressPosition] = lastFacetAddress;\n _facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\n }\n _facetAddresses.pop();\n delete _facetFunctionSelectors[facetAddress];\n }\n }\n\n /**\n * @dev Ensure that the given address has contract code deployed\n * @param _contract The address to check for contract code\n * @param _errorMessage The error message to display if the contract code is not deployed\n */\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\n uint256 contractSize;\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize != 0, _errorMessage);\n }\n\n // Find facet for function that is called and execute the\n // function if a facet is found and return any value.\n fallback() external {\n address facet = _selectorToFacetAndPosition[msg.sig].facetAddress;\n require(facet != address(0), \"Diamond: Function does not exist\");\n // Execute public function from facet using delegatecall and return any value.\n assembly {\n // copy function selector and any arguments\n calldatacopy(0, 0, calldatasize())\n // execute function call using the facet\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\n // get any return value\n returndatacopy(0, 0, returndatasize())\n // return any return value or error back to the caller\n switch result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/FacetBaseR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { ComptrollerErrorReporter } from \"../../../../Utils/ErrorReporter.sol\";\nimport { ExponentialNoError } from \"../../../../Utils/ExponentialNoError.sol\";\nimport { IVAIVault, Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { ComptrollerV16StorageR1 } from \"../../ComptrollerStorageR1.sol\";\n\n/**\n * @title FacetBase\n * @author Venus\n * @notice This facet contract contains functions related to access and checks\n */\ncontract FacetBaseR1 is ComptrollerV16StorageR1, ExponentialNoError, ComptrollerErrorReporter {\n using SafeERC20 for IERC20;\n\n /// @notice The initial Venus index for a market\n uint224 public constant venusInitialIndex = 1e36;\n // closeFactorMantissa must be strictly greater than this value\n uint256 internal constant closeFactorMinMantissa = 0.05e18; // 0.05\n // closeFactorMantissa must not exceed this value\n uint256 internal constant closeFactorMaxMantissa = 0.9e18; // 0.9\n // No collateralFactorMantissa may exceed this value\n uint256 internal constant collateralFactorMaxMantissa = 0.9e18; // 0.9\n\n /// @notice Emitted when an account enters a market\n event MarketEntered(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when XVS is distributed to VAI Vault\n event DistributedVAIVaultVenus(uint256 amount);\n\n /// @notice Reverts if the protocol is paused\n function checkProtocolPauseState() internal view {\n require(!protocolPaused, \"protocol is paused\");\n }\n\n /// @notice Reverts if a certain action is paused on a market\n function checkActionPauseState(address market, Action action) internal view {\n require(!actionPaused(market, action), \"action is paused\");\n }\n\n /// @notice Reverts if the caller is not admin\n function ensureAdmin() internal view {\n require(msg.sender == admin, \"only admin can\");\n }\n\n /// @notice Checks the passed address is nonzero\n function ensureNonzeroAddress(address someone) internal pure {\n require(someone != address(0), \"can't be zero address\");\n }\n\n /// @notice Reverts if the market is not listed\n function ensureListed(Market storage market) internal view {\n require(market.isListed, \"market not listed\");\n }\n\n /// @notice Reverts if the caller is neither admin nor the passed address\n function ensureAdminOr(address privilegedAddress) internal view {\n require(msg.sender == admin || msg.sender == privilegedAddress, \"access denied\");\n }\n\n /// @notice Checks the caller is allowed to call the specified fuction\n function ensureAllowed(string memory functionSig) internal view {\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \"access denied\");\n }\n\n /**\n * @notice Checks if a certain action is paused on a market\n * @param action Action id\n * @param market vToken address\n */\n function actionPaused(address market, Action action) public view returns (bool) {\n return _actionPaused[market][uint256(action)];\n }\n\n /**\n * @notice Get the latest block number\n */\n function getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Get the latest block number with the safe32 check\n */\n function getBlockNumberAsUint32() internal view returns (uint32) {\n return safe32(getBlockNumber(), \"block # > 32 bits\");\n }\n\n /**\n * @notice Transfer XVS to VAI Vault\n */\n function releaseToVault() internal {\n if (releaseStartBlock == 0 || getBlockNumber() < releaseStartBlock) {\n return;\n }\n\n IERC20 xvs_ = IERC20(xvs);\n\n uint256 xvsBalance = xvs_.balanceOf(address(this));\n if (xvsBalance == 0) {\n return;\n }\n\n uint256 actualAmount;\n uint256 deltaBlocks = sub_(getBlockNumber(), releaseStartBlock);\n // releaseAmount = venusVAIVaultRate * deltaBlocks\n uint256 releaseAmount_ = mul_(venusVAIVaultRate, deltaBlocks);\n\n if (xvsBalance >= releaseAmount_) {\n actualAmount = releaseAmount_;\n } else {\n actualAmount = xvsBalance;\n }\n\n if (actualAmount < minReleaseAmount) {\n return;\n }\n\n releaseStartBlock = getBlockNumber();\n\n xvs_.safeTransfer(vaiVaultAddress, actualAmount);\n emit DistributedVAIVaultVenus(actualAmount);\n\n IVAIVault(vaiVaultAddress).updatePendingRewards();\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @dev Note that we calculate the exchangeRateStored for each collateral vToken using stored data,\n * without calculating accumulated interest.\n * @return (possible error code,\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidityInternal(\n address account,\n VToken vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) internal view returns (Error, uint256, uint256) {\n (uint256 err, uint256 liquidity, uint256 shortfall) = comptrollerLens.getHypotheticalAccountLiquidity(\n address(this),\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount\n );\n return (Error(err), liquidity, shortfall);\n }\n\n /**\n * @notice Add the market to the borrower's \"assets in\" for liquidity calculations\n * @param vToken The market to enter\n * @param borrower The address of the account to modify\n * @return Success indicator for whether the market was entered\n */\n function addToMarketInternal(VToken vToken, address borrower) internal returns (Error) {\n checkActionPauseState(address(vToken), Action.ENTER_MARKET);\n Market storage marketToJoin = markets[address(vToken)];\n ensureListed(marketToJoin);\n if (marketToJoin.accountMembership[borrower]) {\n // already joined\n return Error.NO_ERROR;\n }\n // survived the gauntlet, add to list\n // NOTE: we store these somewhat redundantly as a significant optimization\n // this avoids having to iterate through the list for the most common use cases\n // that is, only when we need to perform liquidity checks\n // and not whenever we want to check if an account is in a particular market\n marketToJoin.accountMembership[borrower] = true;\n accountAssets[borrower].push(vToken);\n\n emit MarketEntered(vToken, borrower);\n\n return Error.NO_ERROR;\n }\n\n /**\n * @notice Checks for the user is allowed to redeem tokens\n * @param vToken Address of the market\n * @param redeemer Address of the user\n * @param redeemTokens Amount of tokens to redeem\n * @return Success indicator for redeem is allowed or not\n */\n function redeemAllowedInternal(\n address vToken,\n address redeemer,\n uint256 redeemTokens\n ) internal view returns (uint256) {\n ensureListed(markets[vToken]);\n /* If the redeemer is not 'in' the market, then we can bypass the liquidity check */\n if (!markets[vToken].accountMembership[redeemer]) {\n return uint256(Error.NO_ERROR);\n }\n /* Otherwise, perform a hypothetical liquidity check to guard against shortfall */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n redeemer,\n VToken(vToken),\n redeemTokens,\n 0\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Returns the XVS address\n * @return The address of XVS token\n */\n function getXVSAddress() external view returns (address) {\n return xvs;\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/MarketFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { IMarketFacetR1 } from \"../interfaces/IMarketFacetR1.sol\";\nimport { FacetBaseR1 } from \"./FacetBaseR1.sol\";\n\n/**\n * @title MarketFacet\n * @author Venus\n * @dev This facet contains all the methods related to the market's management in the pool\n * @notice This facet contract contains functions regarding markets\n */\ncontract MarketFacetR1 is IMarketFacetR1, FacetBaseR1 {\n /// @notice Emitted when an admin supports a market\n event MarketListed(VToken indexed vToken);\n\n /// @notice Emitted when an account exits a market\n event MarketExited(VToken indexed vToken, address indexed account);\n\n /// @notice Emitted when the borrowing or redeeming delegate rights are updated for an account\n event DelegateUpdated(address indexed approver, address indexed delegate, bool approved);\n\n /// @notice Emitted when an admin unlists a market\n event MarketUnlisted(address indexed vToken);\n\n /// @notice Indicator that this is a Comptroller contract (for inspection)\n function isComptroller() public pure returns (bool) {\n return true;\n }\n\n /**\n * @notice Returns the assets an account has entered\n * @param account The address of the account to pull assets for\n * @return A dynamic list with the assets the account has entered\n */\n function getAssetsIn(address account) external view returns (VToken[] memory) {\n uint256 len;\n VToken[] memory _accountAssets = accountAssets[account];\n uint256 _accountAssetsLength = _accountAssets.length;\n\n VToken[] memory assetsIn = new VToken[](_accountAssetsLength);\n\n for (uint256 i; i < _accountAssetsLength; ++i) {\n Market storage market = markets[address(_accountAssets[i])];\n if (market.isListed) {\n assetsIn[len] = _accountAssets[i];\n ++len;\n }\n }\n\n assembly {\n mstore(assetsIn, len)\n }\n\n return assetsIn;\n }\n\n /**\n * @notice Return all of the markets\n * @dev The automatic getter may be used to access an individual market\n * @return The list of market addresses\n */\n function getAllMarkets() external view returns (VToken[] memory) {\n return allMarkets;\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenBorrowed The address of the borrowed vToken\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateCalculateSeizeTokens(\n address(this),\n vTokenBorrowed,\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Calculate number of tokens of collateral asset to seize given an underlying amount\n * @dev Used in liquidation (called in vToken.liquidateBorrowFresh)\n * @param vTokenCollateral The address of the collateral vToken\n * @param actualRepayAmount The amount of vTokenBorrowed underlying to convert into vTokenCollateral tokens\n * @return (errorCode, number of vTokenCollateral tokens to be seized in a liquidation)\n */\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256) {\n (uint256 err, uint256 seizeTokens) = comptrollerLens.liquidateVAICalculateSeizeTokens(\n address(this),\n vTokenCollateral,\n actualRepayAmount\n );\n return (err, seizeTokens);\n }\n\n /**\n * @notice Returns whether the given account is entered in the given asset\n * @param account The address of the account to check\n * @param vToken The vToken to check\n * @return True if the account is in the asset, otherwise false\n */\n function checkMembership(address account, VToken vToken) external view returns (bool) {\n return markets[address(vToken)].accountMembership[account];\n }\n\n /**\n * @notice Check if a market is marked as listed (active)\n * @param vToken vToken Address for the market to check\n * @return listed True if listed otherwise false\n */\n function isMarketListed(VToken vToken) external view returns (bool) {\n return markets[address(vToken)].isListed;\n }\n\n /**\n * @notice Add assets to be included in account liquidity calculation\n * @param vTokens The list of addresses of the vToken markets to be enabled\n * @return Success indicator for whether each corresponding market was entered\n */\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory) {\n uint256 len = vTokens.length;\n\n uint256[] memory results = new uint256[](len);\n for (uint256 i; i < len; ++i) {\n results[i] = uint256(addToMarketInternal(VToken(vTokens[i]), msg.sender));\n }\n\n return results;\n }\n\n /**\n * @notice Unlist a market by setting isListed to false\n * @dev Checks if market actions are paused and borrowCap/supplyCap/CF are set to 0\n * @param market The address of the market (vToken) to unlist\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function unlistMarket(address market) external returns (uint256) {\n ensureAllowed(\"unlistMarket(address)\");\n\n Market storage _market = markets[market];\n\n if (!_market.isListed) {\n return fail(Error.MARKET_NOT_LISTED, FailureInfo.UNLIST_MARKET_NOT_LISTED);\n }\n\n require(actionPaused(market, Action.BORROW), \"borrow action is not paused\");\n require(actionPaused(market, Action.MINT), \"mint action is not paused\");\n require(actionPaused(market, Action.REDEEM), \"redeem action is not paused\");\n require(actionPaused(market, Action.REPAY), \"repay action is not paused\");\n require(actionPaused(market, Action.ENTER_MARKET), \"enter market action is not paused\");\n require(actionPaused(market, Action.LIQUIDATE), \"liquidate action is not paused\");\n require(actionPaused(market, Action.SEIZE), \"seize action is not paused\");\n require(actionPaused(market, Action.TRANSFER), \"transfer action is not paused\");\n require(actionPaused(market, Action.EXIT_MARKET), \"exit market action is not paused\");\n\n require(borrowCaps[market] == 0, \"borrow cap is not 0\");\n require(supplyCaps[market] == 0, \"supply cap is not 0\");\n\n require(_market.collateralFactorMantissa == 0, \"collateral factor is not 0\");\n\n _market.isListed = false;\n emit MarketUnlisted(market);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Removes asset from sender's account liquidity calculation\n * @dev Sender must not have an outstanding borrow balance in the asset,\n * or be providing necessary collateral for an outstanding borrow\n * @param vTokenAddress The address of the asset to be removed\n * @return Whether or not the account successfully exited the market\n */\n function exitMarket(address vTokenAddress) external returns (uint256) {\n checkActionPauseState(vTokenAddress, Action.EXIT_MARKET);\n\n VToken vToken = VToken(vTokenAddress);\n /* Get sender tokensHeld and amountOwed underlying from the vToken */\n (uint256 oErr, uint256 tokensHeld, uint256 amountOwed, ) = vToken.getAccountSnapshot(msg.sender);\n require(oErr == 0, \"getAccountSnapshot failed\"); // semi-opaque error code\n\n /* Fail if the sender has a borrow balance */\n if (amountOwed != 0) {\n return fail(Error.NONZERO_BORROW_BALANCE, FailureInfo.EXIT_MARKET_BALANCE_OWED);\n }\n\n /* Fail if the sender is not permitted to redeem all of their tokens */\n uint256 allowed = redeemAllowedInternal(vTokenAddress, msg.sender, tokensHeld);\n if (allowed != 0) {\n return failOpaque(Error.REJECTION, FailureInfo.EXIT_MARKET_REJECTION, allowed);\n }\n\n Market storage marketToExit = markets[address(vToken)];\n\n /* Return true if the sender is not already ‘in’ the market */\n if (!marketToExit.accountMembership[msg.sender]) {\n return uint256(Error.NO_ERROR);\n }\n\n /* Set vToken account membership to false */\n delete marketToExit.accountMembership[msg.sender];\n\n /* Delete vToken from the account’s list of assets */\n // In order to delete vToken, copy last item in list to location of item to be removed, reduce length by 1\n VToken[] storage userAssetList = accountAssets[msg.sender];\n uint256 len = userAssetList.length;\n uint256 i;\n for (; i < len; ++i) {\n if (userAssetList[i] == vToken) {\n userAssetList[i] = userAssetList[len - 1];\n userAssetList.pop();\n break;\n }\n }\n\n // We *must* have found the asset in the list or our redundant data structure is broken\n assert(i < len);\n\n emit MarketExited(vToken, msg.sender);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _supportMarket to support the Isolated Lending Comptroller Interface\n * @param vToken The address of the market (token) to list\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function supportMarket(VToken vToken) external returns (uint256) {\n return __supportMarket(vToken);\n }\n\n /**\n * @notice Add the market to the markets mapping and set it as listed\n * @dev Allows a privileged role to add and list markets to the Comptroller\n * @param vToken The address of the market (token) to list\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _supportMarket(VToken vToken) external returns (uint256) {\n return __supportMarket(vToken);\n }\n\n /**\n * @notice Grants or revokes the borrowing or redeeming delegate rights to / from an account\n * If allowed, the delegate will be able to borrow funds on behalf of the sender\n * Upon a delegated borrow, the delegate will receive the funds, and the borrower\n * will see the debt on their account\n * Upon a delegated redeem, the delegate will receive the redeemed amount and the approver\n * will see a deduction in his vToken balance\n * @param delegate The address to update the rights for\n * @param approved Whether to grant (true) or revoke (false) the borrowing or redeeming rights\n */\n function updateDelegate(address delegate, bool approved) external {\n ensureNonzeroAddress(delegate);\n require(approvedDelegates[msg.sender][delegate] != approved, \"Delegation status unchanged\");\n\n _updateDelegate(msg.sender, delegate, approved);\n }\n\n function _updateDelegate(address approver, address delegate, bool approved) internal {\n approvedDelegates[approver][delegate] = approved;\n emit DelegateUpdated(approver, delegate, approved);\n }\n\n function _addMarketInternal(VToken vToken) internal {\n uint256 allMarketsLength = allMarkets.length;\n for (uint256 i; i < allMarketsLength; ++i) {\n require(allMarkets[i] != vToken, \"already added\");\n }\n allMarkets.push(vToken);\n }\n\n function _initializeMarket(address vToken) internal {\n uint32 blockNumber = getBlockNumberAsUint32();\n\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n\n /*\n * Update market state indices\n */\n if (supplyState.index == 0) {\n // Initialize supply state index with default value\n supplyState.index = venusInitialIndex;\n }\n\n if (borrowState.index == 0) {\n // Initialize borrow state index with default value\n borrowState.index = venusInitialIndex;\n }\n\n /*\n * Update market state block numbers\n */\n supplyState.block = borrowState.block = blockNumber;\n }\n\n function __supportMarket(VToken vToken) internal returns (uint256) {\n ensureAllowed(\"_supportMarket(address)\");\n\n if (markets[address(vToken)].isListed) {\n return fail(Error.MARKET_ALREADY_LISTED, FailureInfo.SUPPORT_MARKET_EXISTS);\n }\n\n vToken.isVToken(); // Sanity check to make sure its really a VToken\n\n // Note that isVenus is not in active use anymore\n Market storage newMarket = markets[address(vToken)];\n newMarket.isListed = true;\n newMarket.isVenus = false;\n newMarket.collateralFactorMantissa = 0;\n\n _addMarketInternal(vToken);\n _initializeMarket(address(vToken));\n\n emit MarketListed(vToken);\n\n return uint256(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/PolicyFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { IPolicyFacetR1 } from \"../interfaces/IPolicyFacetR1.sol\";\n\nimport { XVSRewardsHelperR1 } from \"./XVSRewardsHelperR1.sol\";\n\n/**\n * @title PolicyFacet\n * @author Venus\n * @dev This facet contains all the hooks used while transferring the assets\n * @notice This facet contract contains all the external pre-hook functions related to vToken\n */\ncontract PolicyFacetR1 is IPolicyFacetR1, XVSRewardsHelperR1 {\n /// @notice Emitted when a new borrow-side XVS speed is calculated for a market\n event VenusBorrowSpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /// @notice Emitted when a new supply-side XVS speed is calculated for a market\n event VenusSupplySpeedUpdated(VToken indexed vToken, uint256 newSpeed);\n\n /**\n * @notice Checks if the account should be allowed to mint tokens in the given market\n * @param vToken The market to verify the mint against\n * @param minter The account which would get the minted tokens\n * @param mintAmount The amount of underlying being supplied to the market in exchange for tokens\n * @return 0 if the mint is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.MINT);\n ensureListed(markets[vToken]);\n\n uint256 supplyCap = supplyCaps[vToken];\n require(supplyCap != 0, \"market supply cap is 0\");\n\n uint256 vTokenSupply = VToken(vToken).totalSupply();\n Exp memory exchangeRate = Exp({ mantissa: VToken(vToken).exchangeRateStored() });\n uint256 nextTotalSupply = mul_ScalarTruncateAddUInt(exchangeRate, vTokenSupply, mintAmount);\n require(nextTotalSupply <= supplyCap, \"market supply cap reached\");\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, minter);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates mint, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being minted\n * @param minter The address minting the tokens\n * @param actualMintAmount The amount of the underlying asset being minted\n * @param mintTokens The number of tokens being minted\n */\n // solhint-disable-next-line no-unused-vars\n function mintVerify(address vToken, address minter, uint256 actualMintAmount, uint256 mintTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(minter, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to redeem tokens in the given market\n * @param vToken The market to verify the redeem against\n * @param redeemer The account which would redeem the tokens\n * @param redeemTokens The number of vTokens to exchange for the underlying asset in the market\n * @return 0 if the redeem is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REDEEM);\n\n uint256 allowed = redeemAllowedInternal(vToken, redeemer, redeemTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, redeemer);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates redeem, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being redeemed\n * @param redeemer The address redeeming the tokens\n * @param redeemAmount The amount of the underlying asset being redeemed\n * @param redeemTokens The number of tokens being redeemed\n */\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external {\n require(redeemTokens != 0 || redeemAmount == 0, \"redeemTokens zero\");\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(redeemer, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to borrow the underlying asset of the given market\n * @param vToken The market to verify the borrow against\n * @param borrower The account which would borrow the asset\n * @param borrowAmount The amount of underlying the account would borrow\n * @return 0 if the borrow is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.BORROW);\n ensureListed(markets[vToken]);\n\n uint256 borrowCap = borrowCaps[vToken];\n require(borrowCap != 0, \"market borrow cap is 0\");\n\n if (!markets[vToken].accountMembership[borrower]) {\n // only vTokens may call borrowAllowed if borrower not in market\n require(msg.sender == vToken, \"sender must be vToken\");\n\n // attempt to add borrower to the market\n Error err = addToMarketInternal(VToken(vToken), borrower);\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n }\n\n if (oracle.getUnderlyingPrice(vToken) == 0) {\n return uint256(Error.PRICE_ERROR);\n }\n\n uint256 nextTotalBorrows = add_(VToken(vToken).totalBorrows(), borrowAmount);\n require(nextTotalBorrows <= borrowCap, \"market borrow cap reached\");\n\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n borrower,\n VToken(vToken),\n 0,\n borrowAmount\n );\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall != 0) {\n return uint256(Error.INSUFFICIENT_LIQUIDITY);\n }\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates borrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset whose underlying is being borrowed\n * @param borrower The address borrowing the underlying\n * @param borrowAmount The amount of the underlying asset requested to borrow\n */\n // solhint-disable-next-line no-unused-vars\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to repay a borrow in the given market\n * @param vToken The market to verify the repay against\n * @param payer The account which would repay the asset\n * @param borrower The account which borrowed the asset\n * @param repayAmount The amount of the underlying asset the account would repay\n * @return 0 if the repay is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function repayBorrowAllowed(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 repayAmount // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.REPAY);\n ensureListed(markets[vToken]);\n\n // Keep the flywheel moving\n Exp memory borrowIndex = Exp({ mantissa: VToken(vToken).borrowIndex() });\n updateVenusBorrowIndex(vToken, borrowIndex);\n distributeBorrowerVenus(vToken, borrower, borrowIndex);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates repayBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being repaid\n * @param payer The address repaying the borrow\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n */\n function repayBorrowVerify(\n address vToken,\n address payer, // solhint-disable-line no-unused-vars\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 borrowerIndex // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vToken);\n }\n }\n\n /**\n * @notice Checks if the liquidation should be allowed to occur\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param repayAmount The amount of underlying being repaid\n */\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256) {\n checkProtocolPauseState();\n\n // if we want to pause liquidating to vTokenCollateral, we should pause seizing\n checkActionPauseState(vTokenBorrowed, Action.LIQUIDATE);\n\n if (liquidatorContract != address(0) && liquidator != liquidatorContract) {\n return uint256(Error.UNAUTHORIZED);\n }\n\n ensureListed(markets[vTokenCollateral]);\n\n uint256 borrowBalance;\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n borrowBalance = VToken(vTokenBorrowed).borrowBalanceStored(borrower);\n } else {\n borrowBalance = vaiController.getVAIRepayAmount(borrower);\n }\n\n if (isForcedLiquidationEnabled[vTokenBorrowed] || isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed]) {\n if (repayAmount > borrowBalance) {\n return uint(Error.TOO_MUCH_REPAY);\n }\n return uint(Error.NO_ERROR);\n }\n\n /* The borrower must have shortfall in order to be liquidatable */\n (Error err, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(borrower, VToken(address(0)), 0, 0);\n if (err != Error.NO_ERROR) {\n return uint256(err);\n }\n if (shortfall == 0) {\n return uint256(Error.INSUFFICIENT_SHORTFALL);\n }\n\n // The liquidator may not repay more than what is allowed by the closeFactor\n //-- maxClose = multipy of closeFactorMantissa and borrowBalance\n if (repayAmount > mul_ScalarTruncate(Exp({ mantissa: closeFactorMantissa }), borrowBalance)) {\n return uint256(Error.TOO_MUCH_REPAY);\n }\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates liquidateBorrow, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param actualRepayAmount The amount of underlying being repaid\n * @param seizeTokens The amount of collateral token that will be seized\n */\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 actualRepayAmount, // solhint-disable-line no-unused-vars\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenBorrowed);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenBorrowed);\n }\n }\n\n /**\n * @notice Checks if the seizing of assets should be allowed to occur\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vTokenCollateral, Action.SEIZE);\n\n Market storage market = markets[vTokenCollateral];\n\n // We've added VAIController as a borrowed token list check for seize\n ensureListed(market);\n\n if (!market.accountMembership[borrower]) {\n return uint256(Error.MARKET_NOT_COLLATERAL);\n }\n\n if (address(vTokenBorrowed) != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n }\n\n if (VToken(vTokenCollateral).comptroller() != VToken(vTokenBorrowed).comptroller()) {\n return uint256(Error.COMPTROLLER_MISMATCH);\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vTokenCollateral);\n distributeSupplierVenus(vTokenCollateral, borrower);\n distributeSupplierVenus(vTokenCollateral, liquidator);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates seize, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vTokenCollateral Asset which was used as collateral and will be seized\n * @param vTokenBorrowed Asset which was borrowed by the borrower\n * @param liquidator The address repaying the borrow and seizing the collateral\n * @param borrower The address of the borrower\n * @param seizeTokens The number of collateral tokens to seize\n */\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed, // solhint-disable-line no-unused-vars\n address liquidator,\n address borrower,\n uint256 seizeTokens // solhint-disable-line no-unused-vars\n ) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(borrower, vTokenCollateral);\n prime.accrueInterestAndUpdateScore(liquidator, vTokenCollateral);\n }\n }\n\n /**\n * @notice Checks if the account should be allowed to transfer tokens in the given market\n * @param vToken The market to verify the transfer against\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n * @return 0 if the transfer is allowed, otherwise a semi-opaque error code (See ErrorReporter.sol)\n */\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256) {\n // Pausing is a very serious situation - we revert to sound the alarms\n checkProtocolPauseState();\n checkActionPauseState(vToken, Action.TRANSFER);\n\n // Currently the only consideration is whether or not\n // the src is allowed to redeem this many tokens\n uint256 allowed = redeemAllowedInternal(vToken, src, transferTokens);\n if (allowed != uint256(Error.NO_ERROR)) {\n return allowed;\n }\n\n // Keep the flywheel moving\n updateVenusSupplyIndex(vToken);\n distributeSupplierVenus(vToken, src);\n distributeSupplierVenus(vToken, dst);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Validates transfer, accrues interest and updates score in prime. Reverts on rejection. May emit logs.\n * @param vToken Asset being transferred\n * @param src The account which sources the tokens\n * @param dst The account which receives the tokens\n * @param transferTokens The number of vTokens to transfer\n */\n // solhint-disable-next-line no-unused-vars\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external {\n if (address(prime) != address(0)) {\n prime.accrueInterestAndUpdateScore(src, vToken);\n prime.accrueInterestAndUpdateScore(dst, vToken);\n }\n }\n\n /**\n * @notice Alias to getAccountLiquidity to support the Isolated Lending Comptroller Interface\n * @param account The account get liquidity for\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n * account shortfall below collateral requirements)\n */\n function getBorrowingPower(address account) external view returns (uint256, uint256, uint256) {\n return _getAccountLiquidity(account);\n }\n\n /**\n * @notice Determine the current account liquidity wrt collateral requirements\n * @param account The account get liquidity for\n * @return (possible error code (semi-opaque),\n account liquidity in excess of collateral requirements,\n * account shortfall below collateral requirements)\n */\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256) {\n return _getAccountLiquidity(account);\n }\n\n /**\n * @notice Determine what the account liquidity would be if the given amounts were redeemed/borrowed\n * @param vTokenModify The market to hypothetically redeem/borrow in\n * @param account The account to determine liquidity for\n * @param redeemTokens The number of tokens to hypothetically redeem\n * @param borrowAmount The amount of underlying to hypothetically borrow\n * @return (possible error code (semi-opaque),\n hypothetical account liquidity in excess of collateral requirements,\n * hypothetical account shortfall below collateral requirements)\n */\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n account,\n VToken(vTokenModify),\n redeemTokens,\n borrowAmount\n );\n return (uint256(err), liquidity, shortfall);\n }\n\n // setter functionality\n /**\n * @notice Set XVS speed for a single market\n * @dev Allows the contract admin to set XVS speed for a market\n * @param vTokens The market whose XVS speed to update\n * @param supplySpeeds New XVS speed for supply\n * @param borrowSpeeds New XVS speed for borrow\n */\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external {\n ensureAdmin();\n\n uint256 numTokens = vTokens.length;\n require(numTokens == supplySpeeds.length && numTokens == borrowSpeeds.length, \"invalid input\");\n\n for (uint256 i; i < numTokens; ++i) {\n ensureNonzeroAddress(address(vTokens[i]));\n setVenusSpeedInternal(vTokens[i], supplySpeeds[i], borrowSpeeds[i]);\n }\n }\n\n function _getAccountLiquidity(address account) internal view returns (uint256, uint256, uint256) {\n (Error err, uint256 liquidity, uint256 shortfall) = getHypotheticalAccountLiquidityInternal(\n account,\n VToken(address(0)),\n 0,\n 0\n );\n\n return (uint256(err), liquidity, shortfall);\n }\n\n function setVenusSpeedInternal(VToken vToken, uint256 supplySpeed, uint256 borrowSpeed) internal {\n ensureListed(markets[address(vToken)]);\n\n if (venusSupplySpeeds[address(vToken)] != supplySpeed) {\n // Supply speed updated so let's update supply state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n\n updateVenusSupplyIndex(address(vToken));\n // Update speed and emit event\n venusSupplySpeeds[address(vToken)] = supplySpeed;\n emit VenusSupplySpeedUpdated(vToken, supplySpeed);\n }\n\n if (venusBorrowSpeeds[address(vToken)] != borrowSpeed) {\n // Borrow speed updated so let's update borrow state to ensure that\n // 1. XVS accrued properly for the old speed, and\n // 2. XVS accrued at the new speed starts after this block.\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n\n // Update speed and emit event\n venusBorrowSpeeds[address(vToken)] = borrowSpeed;\n emit VenusBorrowSpeedUpdated(vToken, borrowSpeed);\n }\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/RewardFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { IRewardFacetR1 } from \"../interfaces/IRewardFacetR1.sol\";\nimport { XVSRewardsHelperR1 } from \"./XVSRewardsHelperR1.sol\";\nimport { VBep20Interface } from \"../../../../Tokens/VTokens/VTokenInterfaces.sol\";\n\n/**\n * @title RewardFacet\n * @author Venus\n * @dev This facet contains all the methods related to the reward functionality\n * @notice This facet contract provides the external functions related to all claims and rewards of the protocol\n */\ncontract RewardFacetR1 is IRewardFacetR1, XVSRewardsHelperR1 {\n /// @notice Emitted when Venus is granted by admin\n event VenusGranted(address indexed recipient, uint256 amount);\n\n /// @notice Emitted when XVS are seized for the holder\n event VenusSeized(address indexed holder, uint256 amount);\n\n using SafeERC20 for IERC20;\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets and VAI\n * @param holder The address to claim XVS for\n */\n function claimVenus(address holder) public {\n return claimVenus(holder, allMarkets);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in the specified markets\n * @param holder The address to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n */\n function claimVenus(address holder, VToken[] memory vTokens) public {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, vTokens, true, true);\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function claimVenus(address[] memory holders, VToken[] memory vTokens, bool borrowers, bool suppliers) public {\n claimVenus(holders, vTokens, borrowers, suppliers, false);\n }\n\n /**\n * @notice Claim all the xvs accrued by holder in all markets, a shorthand for `claimVenus` with collateral set to `true`\n * @param holder The address to claim XVS for\n */\n function claimVenusAsCollateral(address holder) external {\n address[] memory holders = new address[](1);\n holders[0] = holder;\n claimVenus(holders, allMarkets, true, true, true);\n }\n\n /**\n * @notice Transfer XVS to the user with user's shortfall considered\n * @dev Note: If there is not enough XVS, we do not perform the transfer all\n * @param user The address of the user to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n * @param shortfall The shortfall of the user\n * @param collateral Whether or not we will use user's venus reward as collateral to pay off the debt\n * @return The amount of XVS which was NOT transferred to the user\n */\n function grantXVSInternal(\n address user,\n uint256 amount,\n uint256 shortfall,\n bool collateral\n ) internal returns (uint256) {\n // If the user is blacklisted, they can't get XVS rewards\n require(\n user != 0xEF044206Db68E40520BfA82D45419d498b4bc7Bf &&\n user != 0x7589dD3355DAE848FDbF75044A3495351655cB1A &&\n user != 0x33df7a7F6D44307E1e5F3B15975b47515e5524c0 &&\n user != 0x24e77E5b74B30b026E9996e4bc3329c881e24968,\n \"Blacklisted\"\n );\n\n IERC20 xvs_ = IERC20(xvs);\n\n if (amount == 0 || amount > xvs_.balanceOf(address(this))) {\n return amount;\n }\n\n if (shortfall == 0) {\n xvs_.safeTransfer(user, amount);\n return 0;\n }\n // If user's bankrupt and doesn't use pending xvs as collateral, don't grant\n // anything, otherwise, we will transfer the pending xvs as collateral to\n // vXVS token and mint vXVS for the user\n //\n // If mintBehalf failed, don't grant any xvs\n require(collateral, \"bankrupt\");\n\n address xvsVToken_ = xvsVToken;\n\n xvs_.safeApprove(xvsVToken_, 0);\n xvs_.safeApprove(xvsVToken_, amount);\n require(VBep20Interface(xvsVToken_).mintBehalf(user, amount) == uint256(Error.NO_ERROR), \"mint behalf error\");\n\n // set venusAccrued[user] to 0\n return 0;\n }\n\n /*** Venus Distribution Admin ***/\n\n /**\n * @notice Transfer XVS to the recipient\n * @dev Allows the contract admin to transfer XVS to any recipient based on the recipient's shortfall\n * Note: If there is not enough XVS, we do not perform the transfer all\n * @param recipient The address of the recipient to transfer XVS to\n * @param amount The amount of XVS to (possibly) transfer\n */\n function _grantXVS(address recipient, uint256 amount) external {\n ensureAdmin();\n uint256 amountLeft = grantXVSInternal(recipient, amount, 0, false);\n require(amountLeft == 0, \"no xvs\");\n emit VenusGranted(recipient, amount);\n }\n\n /**\n * @dev Seize XVS tokens from the specified holders and transfer to recipient\n * @notice Seize XVS rewards allocated to holders\n * @param holders Addresses of the XVS holders\n * @param recipient Address of the XVS token recipient\n * @return The total amount of XVS tokens seized and transferred to recipient\n */\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256) {\n ensureAllowed(\"seizeVenus(address[],address)\");\n\n uint256 holdersLength = holders.length;\n uint256 totalHoldings;\n\n updateAndDistributeRewardsInternal(holders, allMarkets, true, true);\n for (uint256 j; j < holdersLength; ++j) {\n address holder = holders[j];\n uint256 userHolding = venusAccrued[holder];\n\n if (userHolding != 0) {\n totalHoldings += userHolding;\n delete venusAccrued[holder];\n }\n\n emit VenusSeized(holder, userHolding);\n }\n\n if (totalHoldings != 0) {\n IERC20(xvs).safeTransfer(recipient, totalHoldings);\n emit VenusGranted(recipient, totalHoldings);\n }\n\n return totalHoldings;\n }\n\n /**\n * @notice Claim all xvs accrued by the holders\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n * @param collateral Whether or not to use XVS earned as collateral, only takes effect when the holder has a shortfall\n */\n function claimVenus(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) public {\n uint256 holdersLength = holders.length;\n\n updateAndDistributeRewardsInternal(holders, vTokens, borrowers, suppliers);\n for (uint256 j; j < holdersLength; ++j) {\n address holder = holders[j];\n\n // If there is a positive shortfall, the XVS reward is accrued,\n // but won't be granted to this holder\n (, , uint256 shortfall) = getHypotheticalAccountLiquidityInternal(holder, VToken(address(0)), 0, 0);\n\n uint256 value = venusAccrued[holder];\n delete venusAccrued[holder];\n\n uint256 returnAmount = grantXVSInternal(holder, value, shortfall, collateral);\n\n // returnAmount can only be positive if balance of xvsAddress is less than grant amount(venusAccrued[holder])\n if (returnAmount != 0) {\n venusAccrued[holder] = returnAmount;\n }\n }\n }\n\n /**\n * @notice Update and distribute tokens\n * @param holders The addresses to claim XVS for\n * @param vTokens The list of markets to claim XVS in\n * @param borrowers Whether or not to claim XVS earned by borrowing\n * @param suppliers Whether or not to claim XVS earned by supplying\n */\n function updateAndDistributeRewardsInternal(\n address[] memory holders,\n VToken[] memory vTokens,\n bool borrowers,\n bool suppliers\n ) internal {\n uint256 j;\n uint256 holdersLength = holders.length;\n uint256 vTokensLength = vTokens.length;\n\n for (uint256 i; i < vTokensLength; ++i) {\n VToken vToken = vTokens[i];\n ensureListed(markets[address(vToken)]);\n if (borrowers) {\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n for (j = 0; j < holdersLength; ++j) {\n distributeBorrowerVenus(address(vToken), holders[j], borrowIndex);\n }\n }\n\n if (suppliers) {\n updateVenusSupplyIndex(address(vToken));\n for (j = 0; j < holdersLength; ++j) {\n distributeSupplierVenus(address(vToken), holders[j]);\n }\n }\n }\n }\n\n /**\n * @notice Returns the XVS vToken address\n * @return The address of XVS vToken\n */\n function getXVSVTokenAddress() external view returns (address) {\n return xvsVToken;\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/SetterFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { ComptrollerLensInterfaceR1 } from \"../../ComptrollerLensInterfaceR1.sol\";\nimport { VAIControllerInterface } from \"../../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { IPrime } from \"../../../../Tokens/Prime/IPrime.sol\";\nimport { ISetterFacetR1 } from \"../interfaces/ISetterFacetR1.sol\";\nimport { FacetBaseR1 } from \"./FacetBaseR1.sol\";\n\n/**\n * @title SetterFacet\n * @author Venus\n * @dev This facet contains all the setters for the states\n * @notice This facet contract contains all the configurational setter functions\n */\ncontract SetterFacetR1 is ISetterFacetR1, FacetBaseR1 {\n /// @notice Emitted when close factor is changed by admin\n event NewCloseFactor(uint256 oldCloseFactorMantissa, uint256 newCloseFactorMantissa);\n\n /// @notice Emitted when a collateral factor is changed by admin\n event NewCollateralFactor(\n VToken indexed vToken,\n uint256 oldCollateralFactorMantissa,\n uint256 newCollateralFactorMantissa\n );\n\n /// @notice Emitted when liquidation incentive is changed by admin\n event NewLiquidationIncentive(uint256 oldLiquidationIncentiveMantissa, uint256 newLiquidationIncentiveMantissa);\n\n /// @notice Emitted when price oracle is changed\n event NewPriceOracle(ResilientOracleInterface oldPriceOracle, ResilientOracleInterface newPriceOracle);\n\n /// @notice Emitted when borrow cap for a vToken is changed\n event NewBorrowCap(VToken indexed vToken, uint256 newBorrowCap);\n\n /// @notice Emitted when VAIController is changed\n event NewVAIController(VAIControllerInterface oldVAIController, VAIControllerInterface newVAIController);\n\n /// @notice Emitted when VAI mint rate is changed by admin\n event NewVAIMintRate(uint256 oldVAIMintRate, uint256 newVAIMintRate);\n\n /// @notice Emitted when protocol state is changed by admin\n event ActionProtocolPaused(bool state);\n\n /// @notice Emitted when treasury guardian is changed\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\n\n /// @notice Emitted when treasury address is changed\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\n\n /// @notice Emitted when treasury percent is changed\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\n\n /// @notice Emitted when liquidator adress is changed\n event NewLiquidatorContract(address oldLiquidatorContract, address newLiquidatorContract);\n\n /// @notice Emitted when ComptrollerLens address is changed\n event NewComptrollerLens(address oldComptrollerLens, address newComptrollerLens);\n\n /// @notice Emitted when supply cap for a vToken is changed\n event NewSupplyCap(VToken indexed vToken, uint256 newSupplyCap);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\n\n /// @notice Emitted when pause guardian is changed\n event NewPauseGuardian(address oldPauseGuardian, address newPauseGuardian);\n\n /// @notice Emitted when an action is paused on a market\n event ActionPausedMarket(VToken indexed vToken, Action indexed action, bool pauseState);\n\n /// @notice Emitted when VAI Vault info is changed\n event NewVAIVaultInfo(address indexed vault_, uint256 releaseStartBlock_, uint256 releaseInterval_);\n\n /// @notice Emitted when Venus VAI Vault rate is changed\n event NewVenusVAIVaultRate(uint256 oldVenusVAIVaultRate, uint256 newVenusVAIVaultRate);\n\n /// @notice Emitted when prime token contract address is changed\n event NewPrimeToken(IPrime oldPrimeToken, IPrime newPrimeToken);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for all users in a market\n event IsForcedLiquidationEnabledUpdated(address indexed vToken, bool enable);\n\n /// @notice Emitted when forced liquidation is enabled or disabled for a user borrowing in a market\n event IsForcedLiquidationEnabledForUserUpdated(address indexed borrower, address indexed vToken, bool enable);\n\n /// @notice Emitted when XVS token address is changed\n event NewXVSToken(address indexed oldXVS, address indexed newXVS);\n\n /// @notice Emitted when XVS vToken address is changed\n event NewXVSVToken(address indexed oldXVSVToken, address indexed newXVSVToken);\n\n /**\n * @notice Compare two addresses to ensure they are different\n * @param oldAddress The original address to compare\n * @param newAddress The new address to compare\n */\n modifier compareAddress(address oldAddress, address newAddress) {\n require(oldAddress != newAddress, \"old address is same as new address\");\n _;\n }\n\n /**\n * @notice Compare two values to ensure they are different\n * @param oldValue The original value to compare\n * @param newValue The new value to compare\n */\n modifier compareValue(uint256 oldValue, uint256 newValue) {\n require(oldValue != newValue, \"old value is same as new value\");\n _;\n }\n\n /**\n * @notice Alias to _setPriceOracle to support the Isolated Lending Comptroller Interface\n * @param newOracle The new price oracle to set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\n return __setPriceOracle(newOracle);\n }\n\n /**\n * @notice Sets a new price oracle for the comptroller\n * @dev Allows the contract admin to set a new price oracle used by the Comptroller\n * @param newOracle The new price oracle to set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256) {\n return __setPriceOracle(newOracle);\n }\n\n /**\n * @notice Alias to _setCloseFactor to support the Isolated Lending Comptroller Interface\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\n return __setCloseFactor(newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the closeFactor used when liquidating borrows\n * @dev Allows the contract admin to set the closeFactor used to liquidate borrows\n * @param newCloseFactorMantissa New close factor, scaled by 1e18\n * @return uint256 0=success, otherwise will revert\n */\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256) {\n return __setCloseFactor(newCloseFactorMantissa);\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Allows the contract admin to set the address of access control of this contract\n * @param newAccessControlAddress New address for the access control\n * @return uint256 0=success, otherwise will revert\n */\n function _setAccessControl(\n address newAccessControlAddress\n ) external compareAddress(accessControl, newAccessControlAddress) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newAccessControlAddress);\n\n address oldAccessControlAddress = accessControl;\n\n accessControl = newAccessControlAddress;\n emit NewAccessControl(oldAccessControlAddress, newAccessControlAddress);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _setCollateralFactor to support the Isolated Lending Comptroller Interface\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @param newLiquidationThresholdMantissa The new liquidation threshold, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256) {\n require(\n newCollateralFactorMantissa == newLiquidationThresholdMantissa,\n \"collateral factor and liquidation threshold must be the same\"\n );\n return __setCollateralFactor(vToken, newCollateralFactorMantissa);\n }\n\n /**\n * @notice Sets the collateralFactor for a market\n * @dev Allows a privileged role to set the collateralFactorMantissa\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor, scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function _setCollateralFactor(VToken vToken, uint256 newCollateralFactorMantissa) external returns (uint256) {\n return __setCollateralFactor(vToken, newCollateralFactorMantissa);\n }\n\n /**\n * @notice Alias to _setLiquidationIncentive to support the Isolated Lending Comptroller Interface\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256) {\n return __setLiquidationIncentive(newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Sets liquidationIncentive\n * @dev Allows a privileged role to set the liquidationIncentiveMantissa\n * @param newLiquidationIncentiveMantissa New liquidationIncentive scaled by 1e18\n * @return uint256 0=success, otherwise a failure. (See ErrorReporter for details)\n */\n function _setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256) {\n return __setLiquidationIncentive(newLiquidationIncentiveMantissa);\n }\n\n /**\n * @notice Update the address of the liquidator contract\n * @dev Allows the contract admin to update the address of liquidator contract\n * @param newLiquidatorContract_ The new address of the liquidator contract\n */\n function _setLiquidatorContract(\n address newLiquidatorContract_\n ) external compareAddress(liquidatorContract, newLiquidatorContract_) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(newLiquidatorContract_);\n address oldLiquidatorContract = liquidatorContract;\n liquidatorContract = newLiquidatorContract_;\n emit NewLiquidatorContract(oldLiquidatorContract, newLiquidatorContract_);\n }\n\n /**\n * @notice Admin function to change the Pause Guardian\n * @dev Allows the contract admin to change the Pause Guardian\n * @param newPauseGuardian The address of the new Pause Guardian\n * @return uint256 0=success, otherwise a failure. (See enum Error for details)\n */\n function _setPauseGuardian(\n address newPauseGuardian\n ) external compareAddress(pauseGuardian, newPauseGuardian) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(newPauseGuardian);\n\n // Save current value for inclusion in log\n address oldPauseGuardian = pauseGuardian;\n // Store pauseGuardian with value newPauseGuardian\n pauseGuardian = newPauseGuardian;\n\n // Emit NewPauseGuardian(OldPauseGuardian, NewPauseGuardian)\n emit NewPauseGuardian(oldPauseGuardian, newPauseGuardian);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Alias to _setMarketBorrowCaps to support the Isolated Lending Comptroller Interface\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\n */\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\n }\n\n /**\n * @notice Set the given borrow caps for the given vToken market Borrowing that brings total borrows to or above borrow cap will revert\n * @dev Allows a privileged role to set the borrowing cap for a vToken market. A borrow cap of 0 corresponds to Borrow not allowed\n * @param vTokens The addresses of the markets (tokens) to change the borrow caps for\n * @param newBorrowCaps The new borrow cap values in underlying to be set. A value of 0 corresponds to Borrow not allowed\n */\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external {\n __setMarketBorrowCaps(vTokens, newBorrowCaps);\n }\n\n /**\n * @notice Alias to _setMarketSupplyCaps to support the Isolated Lending Comptroller Interface\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\n }\n\n /**\n * @notice Set the given supply caps for the given vToken market Supply that brings total Supply to or above supply cap will revert\n * @dev Allows a privileged role to set the supply cap for a vToken. A supply cap of 0 corresponds to Minting NotAllowed\n * @param vTokens The addresses of the markets (tokens) to change the supply caps for\n * @param newSupplyCaps The new supply cap values in underlying to be set. A value of 0 corresponds to Minting NotAllowed\n */\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external {\n __setMarketSupplyCaps(vTokens, newSupplyCaps);\n }\n\n /**\n * @notice Set whole protocol pause/unpause state\n * @dev Allows a privileged role to pause/unpause protocol\n * @param state The new state (true=paused, false=unpaused)\n * @return bool The updated state of the protocol\n */\n function _setProtocolPaused(bool state) external returns (bool) {\n ensureAllowed(\"_setProtocolPaused(bool)\");\n\n protocolPaused = state;\n emit ActionProtocolPaused(state);\n return state;\n }\n\n /**\n * @notice Alias to _setActionsPaused to support the Isolated Lending Comptroller Interface\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n __setActionsPaused(markets_, actions_, paused_);\n }\n\n /**\n * @notice Pause/unpause certain actions\n * @dev Allows a privileged role to pause/unpause the protocol action state\n * @param markets_ Markets to pause/unpause the actions on\n * @param actions_ List of action ids to pause/unpause\n * @param paused_ The new paused state (true=paused, false=unpaused)\n */\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external {\n __setActionsPaused(markets_, actions_, paused_);\n }\n\n /**\n * @dev Pause/unpause an action on a market\n * @param market Market to pause/unpause the action on\n * @param action Action id to pause/unpause\n * @param paused The new paused state (true=paused, false=unpaused)\n */\n function setActionPausedInternal(address market, Action action, bool paused) internal {\n ensureListed(markets[market]);\n _actionPaused[market][uint256(action)] = paused;\n emit ActionPausedMarket(VToken(market), action, paused);\n }\n\n /**\n * @notice Sets a new VAI controller\n * @dev Admin function to set a new VAI controller\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIController(\n VAIControllerInterface vaiController_\n ) external compareAddress(address(vaiController), address(vaiController_)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(vaiController_));\n\n VAIControllerInterface oldVaiController = vaiController;\n vaiController = vaiController_;\n emit NewVAIController(oldVaiController, vaiController_);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the VAI mint rate\n * @param newVAIMintRate The new VAI mint rate to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setVAIMintRate(\n uint256 newVAIMintRate\n ) external compareValue(vaiMintRate, newVAIMintRate) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n uint256 oldVAIMintRate = vaiMintRate;\n vaiMintRate = newVAIMintRate;\n emit NewVAIMintRate(oldVAIMintRate, newVAIMintRate);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the minted VAI amount of the `owner`\n * @param owner The address of the account to set\n * @param amount The amount of VAI to set to the account\n * @return The number of minted VAI by `owner`\n */\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256) {\n checkProtocolPauseState();\n\n // Pausing is a very serious situation - we revert to sound the alarms\n require(!mintVAIGuardianPaused && !repayVAIGuardianPaused, \"VAI is paused\");\n // Check caller is vaiController\n if (msg.sender != address(vaiController)) {\n return fail(Error.REJECTION, FailureInfo.SET_MINTED_VAI_REJECTION);\n }\n mintedVAIs[owner] = amount;\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the treasury data.\n * @param newTreasuryGuardian The new address of the treasury guardian to be set\n * @param newTreasuryAddress The new address of the treasury to be set\n * @param newTreasuryPercent The new treasury percent to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256) {\n // Check caller is admin\n ensureAdminOr(treasuryGuardian);\n\n require(newTreasuryPercent < 1e18, \"percent >= 100%\");\n ensureNonzeroAddress(newTreasuryGuardian);\n ensureNonzeroAddress(newTreasuryAddress);\n\n address oldTreasuryGuardian = treasuryGuardian;\n address oldTreasuryAddress = treasuryAddress;\n uint256 oldTreasuryPercent = treasuryPercent;\n\n treasuryGuardian = newTreasuryGuardian;\n treasuryAddress = newTreasuryAddress;\n treasuryPercent = newTreasuryPercent;\n\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\n\n return uint256(Error.NO_ERROR);\n }\n\n /*** Venus Distribution ***/\n\n /**\n * @dev Set ComptrollerLens contract address\n * @param comptrollerLens_ The new ComptrollerLens contract address to be set\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptrollerLens(\n ComptrollerLensInterfaceR1 comptrollerLens_\n ) external virtual compareAddress(address(comptrollerLens), address(comptrollerLens_)) returns (uint256) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the amount of XVS distributed per block to VAI Vault\n * @param venusVAIVaultRate_ The amount of XVS wei per block to distribute to VAI Vault\n */\n function _setVenusVAIVaultRate(\n uint256 venusVAIVaultRate_\n ) external compareValue(venusVAIVaultRate, venusVAIVaultRate_) {\n ensureAdmin();\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n uint256 oldVenusVAIVaultRate = venusVAIVaultRate;\n venusVAIVaultRate = venusVAIVaultRate_;\n emit NewVenusVAIVaultRate(oldVenusVAIVaultRate, venusVAIVaultRate_);\n }\n\n /**\n * @notice Set the VAI Vault infos\n * @param vault_ The address of the VAI Vault\n * @param releaseStartBlock_ The start block of release to VAI Vault\n * @param minReleaseAmount_ The minimum release amount to VAI Vault\n */\n function _setVAIVaultInfo(\n address vault_,\n uint256 releaseStartBlock_,\n uint256 minReleaseAmount_\n ) external compareAddress(vaiVaultAddress, vault_) {\n ensureAdmin();\n ensureNonzeroAddress(vault_);\n if (vaiVaultAddress != address(0)) {\n releaseToVault();\n }\n\n vaiVaultAddress = vault_;\n releaseStartBlock = releaseStartBlock_;\n minReleaseAmount = minReleaseAmount_;\n emit NewVAIVaultInfo(vault_, releaseStartBlock_, minReleaseAmount_);\n }\n\n /**\n * @notice Alias to _setPrimeToken to support the Isolated Lending Comptroller Interface\n * @param _prime The new prime token contract to be set\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function setPrimeToken(IPrime _prime) external returns (uint256) {\n return __setPrimeToken(_prime);\n }\n\n /**\n * @notice Sets the prime token contract for the comptroller\n * @param _prime The new prime token contract to be set\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPrimeToken(IPrime _prime) external returns (uint256) {\n return __setPrimeToken(_prime);\n }\n\n /**\n * @notice Alias to _setForcedLiquidation to support the Isolated Lending Comptroller Interface\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n __setForcedLiquidation(vTokenBorrowed, enable);\n }\n\n /** @notice Enables forced liquidations for a market. If forced liquidation is enabled,\n * borrows in the market may be liquidated regardless of the account liquidity\n * @dev Allows a privileged role to set enable/disable forced liquidations\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidation(address vTokenBorrowed, bool enable) external {\n __setForcedLiquidation(vTokenBorrowed, enable);\n }\n\n /**\n * @notice Enables forced liquidations for user's borrows in a certain market. If forced\n * liquidation is enabled, user's borrows in the market may be liquidated regardless of\n * the account liquidity. Forced liquidation may be enabled for a user even if it is not\n * enabled for the entire market.\n * @param borrower The address of the borrower\n * @param vTokenBorrowed Borrowed vToken\n * @param enable Whether to enable forced liquidations\n */\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external {\n ensureAllowed(\"_setForcedLiquidationForUser(address,address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n }\n isForcedLiquidationEnabledForUser[borrower][vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledForUserUpdated(borrower, vTokenBorrowed, enable);\n }\n\n /**\n * @notice Set the address of the XVS token\n * @param xvs_ The address of the XVS token\n */\n function _setXVSToken(address xvs_) external {\n ensureAdmin();\n ensureNonzeroAddress(xvs_);\n\n emit NewXVSToken(xvs, xvs_);\n xvs = xvs_;\n }\n\n /**\n * @notice Set the address of the XVS vToken\n * @param xvsVToken_ The address of the XVS vToken\n */\n function _setXVSVToken(address xvsVToken_) external {\n ensureAdmin();\n ensureNonzeroAddress(xvsVToken_);\n\n address underlying = VToken(xvsVToken_).underlying();\n require(underlying == xvs, \"invalid xvs vtoken address\");\n\n emit NewXVSVToken(xvsVToken, xvsVToken_);\n xvsVToken = xvsVToken_;\n }\n\n /**\n * @dev Updates the valid price oracle. Used by _setPriceOracle and setPriceOracle\n * @param newOracle The new price oracle to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setPriceOracle(\n ResilientOracleInterface newOracle\n ) internal compareAddress(address(oracle), address(newOracle)) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n ensureNonzeroAddress(address(newOracle));\n\n // Track the old oracle for the comptroller\n ResilientOracleInterface oldOracle = oracle;\n\n // Set comptroller's oracle to newOracle\n oracle = newOracle;\n\n // Emit NewPriceOracle(oldOracle, newOracle)\n emit NewPriceOracle(oldOracle, newOracle);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the close factor. Used by _setCloseFactor and setCloseFactor\n * @param newCloseFactorMantissa The new close factor to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setCloseFactor(\n uint256 newCloseFactorMantissa\n ) internal compareValue(closeFactorMantissa, newCloseFactorMantissa) returns (uint256) {\n // Check caller is admin\n ensureAdmin();\n\n Exp memory newCloseFactorExp = Exp({ mantissa: newCloseFactorMantissa });\n\n //-- Check close factor <= 0.9\n Exp memory highLimit = Exp({ mantissa: closeFactorMaxMantissa });\n //-- Check close factor >= 0.05\n Exp memory lowLimit = Exp({ mantissa: closeFactorMinMantissa });\n\n if (lessThanExp(highLimit, newCloseFactorExp) || greaterThanExp(lowLimit, newCloseFactorExp)) {\n return fail(Error.INVALID_CLOSE_FACTOR, FailureInfo.SET_CLOSE_FACTOR_VALIDATION);\n }\n\n uint256 oldCloseFactorMantissa = closeFactorMantissa;\n closeFactorMantissa = newCloseFactorMantissa;\n emit NewCloseFactor(oldCloseFactorMantissa, newCloseFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the collateral factor. Used by _setCollateralFactor and setCollateralFactor\n * @param vToken The market to set the factor on\n * @param newCollateralFactorMantissa The new collateral factor to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa\n )\n internal\n compareValue(markets[address(vToken)].collateralFactorMantissa, newCollateralFactorMantissa)\n returns (uint256)\n {\n // Check caller is allowed by access control manager\n ensureAllowed(\"_setCollateralFactor(address,uint256)\");\n ensureNonzeroAddress(address(vToken));\n\n // Verify market is listed\n Market storage market = markets[address(vToken)];\n ensureListed(market);\n\n Exp memory newCollateralFactorExp = Exp({ mantissa: newCollateralFactorMantissa });\n\n //-- Check collateral factor <= 0.9\n Exp memory highLimit = Exp({ mantissa: collateralFactorMaxMantissa });\n if (lessThanExp(highLimit, newCollateralFactorExp)) {\n return fail(Error.INVALID_COLLATERAL_FACTOR, FailureInfo.SET_COLLATERAL_FACTOR_VALIDATION);\n }\n\n // If collateral factor != 0, fail if price == 0\n if (newCollateralFactorMantissa != 0 && oracle.getUnderlyingPrice(address(vToken)) == 0) {\n return fail(Error.PRICE_ERROR, FailureInfo.SET_COLLATERAL_FACTOR_WITHOUT_PRICE);\n }\n\n // Set market's collateral factor to new collateral factor, remember old value\n uint256 oldCollateralFactorMantissa = market.collateralFactorMantissa;\n market.collateralFactorMantissa = newCollateralFactorMantissa;\n\n // Emit event with asset, old collateral factor, and new collateral factor\n emit NewCollateralFactor(vToken, oldCollateralFactorMantissa, newCollateralFactorMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the liquidation incentive. Used by _setLiquidationIncentive and setLiquidationIncentive\n * @param newLiquidationIncentiveMantissa The new liquidation incentive to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setLiquidationIncentive(\n uint256 newLiquidationIncentiveMantissa\n ) internal compareValue(liquidationIncentiveMantissa, newLiquidationIncentiveMantissa) returns (uint256) {\n ensureAllowed(\"_setLiquidationIncentive(uint256)\");\n\n require(newLiquidationIncentiveMantissa >= 1e18, \"incentive < 1e18\");\n\n // Save current value for use in log\n uint256 oldLiquidationIncentiveMantissa = liquidationIncentiveMantissa;\n // Set liquidation incentive to new incentive\n liquidationIncentiveMantissa = newLiquidationIncentiveMantissa;\n\n // Emit event with old incentive, new incentive\n emit NewLiquidationIncentive(oldLiquidationIncentiveMantissa, newLiquidationIncentiveMantissa);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the borrow caps. Used by _setMarketBorrowCaps and setMarketBorrowCaps\n * @param vTokens The markets to set the borrow caps on\n * @param newBorrowCaps The new borrow caps to be set\n */\n function __setMarketBorrowCaps(VToken[] memory vTokens, uint256[] memory newBorrowCaps) internal {\n ensureAllowed(\"_setMarketBorrowCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numBorrowCaps = newBorrowCaps.length;\n\n require(numMarkets != 0 && numMarkets == numBorrowCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n borrowCaps[address(vTokens[i])] = newBorrowCaps[i];\n emit NewBorrowCap(vTokens[i], newBorrowCaps[i]);\n }\n }\n\n /**\n * @dev Updates the supply caps. Used by _setMarketSupplyCaps and setMarketSupplyCaps\n * @param vTokens The markets to set the supply caps on\n * @param newSupplyCaps The new supply caps to be set\n */\n function __setMarketSupplyCaps(VToken[] memory vTokens, uint256[] memory newSupplyCaps) internal {\n ensureAllowed(\"_setMarketSupplyCaps(address[],uint256[])\");\n\n uint256 numMarkets = vTokens.length;\n uint256 numSupplyCaps = newSupplyCaps.length;\n\n require(numMarkets != 0 && numMarkets == numSupplyCaps, \"invalid input\");\n\n for (uint256 i; i < numMarkets; ++i) {\n supplyCaps[address(vTokens[i])] = newSupplyCaps[i];\n emit NewSupplyCap(vTokens[i], newSupplyCaps[i]);\n }\n }\n\n /**\n * @dev Updates the prime token. Used by _setPrimeToken and setPrimeToken\n * @param _prime The new prime token to be set\n * @return uint256 0=success, otherwise reverted\n */\n function __setPrimeToken(IPrime _prime) internal returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(_prime));\n\n IPrime oldPrime = prime;\n prime = _prime;\n emit NewPrimeToken(oldPrime, _prime);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Updates the forced liquidation. Used by _setForcedLiquidation and setForcedLiquidation\n * @param vTokenBorrowed The market to set the forced liquidation on\n * @param enable Whether to enable forced liquidations\n */\n function __setForcedLiquidation(address vTokenBorrowed, bool enable) internal {\n ensureAllowed(\"_setForcedLiquidation(address,bool)\");\n if (vTokenBorrowed != address(vaiController)) {\n ensureListed(markets[vTokenBorrowed]);\n }\n isForcedLiquidationEnabled[vTokenBorrowed] = enable;\n emit IsForcedLiquidationEnabledUpdated(vTokenBorrowed, enable);\n }\n\n /**\n * @dev Updates the actions paused. Used by _setActionsPaused and setActionsPaused\n * @param markets_ The markets to set the actions paused on\n * @param actions_ The actions to set the paused state on\n * @param paused_ The new paused state to be set\n */\n function __setActionsPaused(address[] memory markets_, Action[] memory actions_, bool paused_) internal {\n ensureAllowed(\"_setActionsPaused(address[],uint8[],bool)\");\n\n uint256 numMarkets = markets_.length;\n uint256 numActions = actions_.length;\n for (uint256 marketIdx; marketIdx < numMarkets; ++marketIdx) {\n for (uint256 actionIdx; actionIdx < numActions; ++actionIdx) {\n setActionPausedInternal(markets_[marketIdx], actions_[actionIdx], paused_);\n }\n }\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/facets/XVSRewardsHelperR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { FacetBaseR1 } from \"./FacetBaseR1.sol\";\n\n/**\n * @title XVSRewardsHelper\n * @author Venus\n * @dev This contract contains internal functions used in RewardFacet and PolicyFacet\n * @notice This facet contract contains the shared functions used by the RewardFacet and PolicyFacet\n */\ncontract XVSRewardsHelperR1 is FacetBaseR1 {\n /// @notice Emitted when XVS is distributed to a borrower\n event DistributedBorrowerVenus(\n VToken indexed vToken,\n address indexed borrower,\n uint256 venusDelta,\n uint256 venusBorrowIndex\n );\n\n /// @notice Emitted when XVS is distributed to a supplier\n event DistributedSupplierVenus(\n VToken indexed vToken,\n address indexed supplier,\n uint256 venusDelta,\n uint256 venusSupplyIndex\n );\n\n /**\n * @notice Accrue XVS to the market by updating the borrow index\n * @param vToken The market whose borrow index to update\n */\n function updateVenusBorrowIndex(address vToken, Exp memory marketBorrowIndex) internal {\n VenusMarketState storage borrowState = venusBorrowState[vToken];\n uint256 borrowSpeed = venusBorrowSpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n uint256 deltaBlocks = sub_(blockNumber, borrowState.block);\n if (deltaBlocks != 0 && borrowSpeed != 0) {\n uint256 borrowAmount = div_(VToken(vToken).totalBorrows(), marketBorrowIndex);\n uint256 accruedVenus = mul_(deltaBlocks, borrowSpeed);\n Double memory ratio = borrowAmount != 0 ? fraction(accruedVenus, borrowAmount) : Double({ mantissa: 0 });\n borrowState.index = safe224(add_(Double({ mantissa: borrowState.index }), ratio).mantissa, \"224\");\n borrowState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n borrowState.block = blockNumber;\n }\n }\n\n /**\n * @notice Accrue XVS to the market by updating the supply index\n * @param vToken The market whose supply index to update\n */\n function updateVenusSupplyIndex(address vToken) internal {\n VenusMarketState storage supplyState = venusSupplyState[vToken];\n uint256 supplySpeed = venusSupplySpeeds[vToken];\n uint32 blockNumber = getBlockNumberAsUint32();\n\n uint256 deltaBlocks = sub_(blockNumber, supplyState.block);\n if (deltaBlocks != 0 && supplySpeed != 0) {\n uint256 supplyTokens = VToken(vToken).totalSupply();\n uint256 accruedVenus = mul_(deltaBlocks, supplySpeed);\n Double memory ratio = supplyTokens != 0 ? fraction(accruedVenus, supplyTokens) : Double({ mantissa: 0 });\n supplyState.index = safe224(add_(Double({ mantissa: supplyState.index }), ratio).mantissa, \"224\");\n supplyState.block = blockNumber;\n } else if (deltaBlocks != 0) {\n supplyState.block = blockNumber;\n }\n }\n\n /**\n * @notice Calculate XVS accrued by a supplier and possibly transfer it to them\n * @param vToken The market in which the supplier is interacting\n * @param supplier The address of the supplier to distribute XVS to\n */\n function distributeSupplierVenus(address vToken, address supplier) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 supplyIndex = venusSupplyState[vToken].index;\n uint256 supplierIndex = venusSupplierIndex[vToken][supplier];\n // Update supplier's index to the current index since we are distributing accrued XVS\n venusSupplierIndex[vToken][supplier] = supplyIndex;\n if (supplierIndex == 0 && supplyIndex >= venusInitialIndex) {\n // Covers the case where users supplied tokens before the market's supply state index was set.\n // Rewards the user with XVS accrued from the start of when supplier rewards were first\n // set for the market.\n supplierIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per vToken accrued\n Double memory deltaIndex = Double({ mantissa: sub_(supplyIndex, supplierIndex) });\n // Multiply of supplierTokens and supplierDelta\n uint256 supplierDelta = mul_(VToken(vToken).balanceOf(supplier), deltaIndex);\n // Addition of supplierAccrued and supplierDelta\n venusAccrued[supplier] = add_(venusAccrued[supplier], supplierDelta);\n emit DistributedSupplierVenus(VToken(vToken), supplier, supplierDelta, supplyIndex);\n }\n\n /**\n * @notice Calculate XVS accrued by a borrower and possibly transfer it to them\n * @dev Borrowers will not begin to accrue until after the first interaction with the protocol\n * @param vToken The market in which the borrower is interacting\n * @param borrower The address of the borrower to distribute XVS to\n */\n function distributeBorrowerVenus(address vToken, address borrower, Exp memory marketBorrowIndex) internal {\n if (address(vaiVaultAddress) != address(0)) {\n releaseToVault();\n }\n uint256 borrowIndex = venusBorrowState[vToken].index;\n uint256 borrowerIndex = venusBorrowerIndex[vToken][borrower];\n // Update borrowers's index to the current index since we are distributing accrued XVS\n venusBorrowerIndex[vToken][borrower] = borrowIndex;\n if (borrowerIndex == 0 && borrowIndex >= venusInitialIndex) {\n // Covers the case where users borrowed tokens before the market's borrow state index was set.\n // Rewards the user with XVS accrued from the start of when borrower rewards were first\n // set for the market.\n borrowerIndex = venusInitialIndex;\n }\n // Calculate change in the cumulative sum of the XVS per borrowed unit accrued\n Double memory deltaIndex = Double({ mantissa: sub_(borrowIndex, borrowerIndex) });\n uint256 borrowerDelta = mul_(div_(VToken(vToken).borrowBalanceStored(borrower), marketBorrowIndex), deltaIndex);\n venusAccrued[borrower] = add_(venusAccrued[borrower], borrowerDelta);\n emit DistributedBorrowerVenus(VToken(vToken), borrower, borrowerDelta, borrowIndex);\n }\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/IDiamondCutR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\ninterface IDiamondCutR1 {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n function diamondCut(FacetCut[] calldata _diamondCut) external;\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/IMarketFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\n\ninterface IMarketFacetR1 {\n function isComptroller() external pure returns (bool);\n\n function liquidateCalculateSeizeTokens(\n address vTokenBorrowed,\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function liquidateVAICalculateSeizeTokens(\n address vTokenCollateral,\n uint256 actualRepayAmount\n ) external view returns (uint256, uint256);\n\n function checkMembership(address account, VToken vToken) external view returns (bool);\n\n function enterMarkets(address[] calldata vTokens) external returns (uint256[] memory);\n\n function exitMarket(address vToken) external returns (uint256);\n\n function _supportMarket(VToken vToken) external returns (uint256);\n\n function supportMarket(VToken vToken) external returns (uint256);\n\n function isMarketListed(VToken vToken) external view returns (bool);\n\n function getAssetsIn(address account) external view returns (VToken[] memory);\n\n function getAllMarkets() external view returns (VToken[] memory);\n\n function updateDelegate(address delegate, bool allowBorrows) external;\n\n function unlistMarket(address market) external returns (uint256);\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/IPolicyFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\n\ninterface IPolicyFacetR1 {\n function mintAllowed(address vToken, address minter, uint256 mintAmount) external returns (uint256);\n\n function mintVerify(address vToken, address minter, uint256 mintAmount, uint256 mintTokens) external;\n\n function redeemAllowed(address vToken, address redeemer, uint256 redeemTokens) external returns (uint256);\n\n function redeemVerify(address vToken, address redeemer, uint256 redeemAmount, uint256 redeemTokens) external;\n\n function borrowAllowed(address vToken, address borrower, uint256 borrowAmount) external returns (uint256);\n\n function borrowVerify(address vToken, address borrower, uint256 borrowAmount) external;\n\n function repayBorrowAllowed(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount\n ) external returns (uint256);\n\n function repayBorrowVerify(\n address vToken,\n address payer,\n address borrower,\n uint256 repayAmount,\n uint256 borrowerIndex\n ) external;\n\n function liquidateBorrowAllowed(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount\n ) external view returns (uint256);\n\n function liquidateBorrowVerify(\n address vTokenBorrowed,\n address vTokenCollateral,\n address liquidator,\n address borrower,\n uint256 repayAmount,\n uint256 seizeTokens\n ) external;\n\n function seizeAllowed(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external returns (uint256);\n\n function seizeVerify(\n address vTokenCollateral,\n address vTokenBorrowed,\n address liquidator,\n address borrower,\n uint256 seizeTokens\n ) external;\n\n function transferAllowed(\n address vToken,\n address src,\n address dst,\n uint256 transferTokens\n ) external returns (uint256);\n\n function transferVerify(address vToken, address src, address dst, uint256 transferTokens) external;\n\n function getAccountLiquidity(address account) external view returns (uint256, uint256, uint256);\n\n function getHypotheticalAccountLiquidity(\n address account,\n address vTokenModify,\n uint256 redeemTokens,\n uint256 borrowAmount\n ) external view returns (uint256, uint256, uint256);\n\n function _setVenusSpeeds(\n VToken[] calldata vTokens,\n uint256[] calldata supplySpeeds,\n uint256[] calldata borrowSpeeds\n ) external;\n\n function getBorrowingPower(\n address account\n ) external view returns (uint256 error, uint256 liquidity, uint256 shortfall);\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/IRewardFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\n\ninterface IRewardFacetR1 {\n function claimVenus(address holder) external;\n\n function claimVenus(address holder, VToken[] calldata vTokens) external;\n\n function claimVenus(address[] calldata holders, VToken[] calldata vTokens, bool borrowers, bool suppliers) external;\n\n function claimVenusAsCollateral(address holder) external;\n\n function _grantXVS(address recipient, uint256 amount) external;\n\n function getXVSVTokenAddress() external view returns (address);\n\n function claimVenus(\n address[] calldata holders,\n VToken[] calldata vTokens,\n bool borrowers,\n bool suppliers,\n bool collateral\n ) external;\n function seizeVenus(address[] calldata holders, address recipient) external returns (uint256);\n}\n" + }, + "contracts/Comptroller/legacy/Diamond/interfaces/ISetterFacetR1.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { VToken } from \"../../../../Tokens/VTokens/VToken.sol\";\nimport { Action } from \"../../ComptrollerInterfaceR1.sol\";\nimport { VAIControllerInterface } from \"../../../../Tokens/VAI/VAIControllerInterface.sol\";\nimport { ComptrollerLensInterfaceR1 } from \"../../ComptrollerLensInterfaceR1.sol\";\nimport { IPrime } from \"../../../../Tokens/Prime/IPrime.sol\";\n\ninterface ISetterFacetR1 {\n function setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\n\n function _setPriceOracle(ResilientOracleInterface newOracle) external returns (uint256);\n\n function setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setCloseFactor(uint256 newCloseFactorMantissa) external returns (uint256);\n\n function _setAccessControl(address newAccessControlAddress) external returns (uint256);\n\n function setCollateralFactor(\n VToken vToken,\n uint256 newCollateralFactorMantissa,\n uint256 newLiquidationThresholdMantissa\n ) external returns (uint256);\n\n function _setCollateralFactor(VToken vToken, uint256 newCollateralFactorMantissa) external returns (uint256);\n\n function setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256);\n\n function _setLiquidationIncentive(uint256 newLiquidationIncentiveMantissa) external returns (uint256);\n\n function _setLiquidatorContract(address newLiquidatorContract_) external;\n\n function _setPauseGuardian(address newPauseGuardian) external returns (uint256);\n\n function setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function _setMarketBorrowCaps(VToken[] calldata vTokens, uint256[] calldata newBorrowCaps) external;\n\n function setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setMarketSupplyCaps(VToken[] calldata vTokens, uint256[] calldata newSupplyCaps) external;\n\n function _setProtocolPaused(bool state) external returns (bool);\n\n function setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\n\n function _setActionsPaused(address[] calldata markets, Action[] calldata actions, bool paused) external;\n\n function _setVAIController(VAIControllerInterface vaiController_) external returns (uint256);\n\n function _setVAIMintRate(uint256 newVAIMintRate) external returns (uint256);\n\n function setMintedVAIOf(address owner, uint256 amount) external returns (uint256);\n\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256);\n\n function _setComptrollerLens(ComptrollerLensInterfaceR1 comptrollerLens_) external returns (uint256);\n\n function _setVenusVAIVaultRate(uint256 venusVAIVaultRate_) external;\n\n function _setVAIVaultInfo(address vault_, uint256 releaseStartBlock_, uint256 minReleaseAmount_) external;\n\n function _setForcedLiquidation(address vToken, bool enable) external;\n\n function setPrimeToken(IPrime _prime) external returns (uint256);\n\n function _setPrimeToken(IPrime _prime) external returns (uint);\n\n function setForcedLiquidation(address vTokenBorrowed, bool enable) external;\n\n function _setForcedLiquidationForUser(address borrower, address vTokenBorrowed, bool enable) external;\n\n function _setXVSToken(address xvs_) external;\n\n function _setXVSVToken(address xvsVToken_) external;\n}\n" + }, + "contracts/Comptroller/Types/PoolMarketId.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\n/// @notice Strongly-typed identifier for pool markets mapping keys\n/// @dev Underlying storage is bytes32: first 12 bytes (96 bits) = poolId, last 20 bytes = vToken address\ntype PoolMarketId is bytes32;\n\n " + }, + "contracts/Comptroller/Unitroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { UnitrollerAdminStorage } from \"./ComptrollerStorage.sol\";\nimport { ComptrollerErrorReporter } from \"../Utils/ErrorReporter.sol\";\n\n/**\n * @title ComptrollerCore\n * @dev Storage for the comptroller is at this address, while execution is delegated to the `comptrollerImplementation`.\n * VTokens should reference this contract as their comptroller.\n */\ncontract Unitroller is UnitrollerAdminStorage, ComptrollerErrorReporter {\n /**\n * @notice Emitted when pendingComptrollerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingComptrollerImplementation is accepted, which means comptroller implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor() {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public returns (uint) {\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public returns (uint) {\n // Check caller is pendingImplementation and pendingImplementation ≠ address(0)\n if (msg.sender != pendingComptrollerImplementation || pendingComptrollerImplementation == address(0)) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldImplementation = comptrollerImplementation;\n address oldPendingImplementation = pendingComptrollerImplementation;\n\n comptrollerImplementation = pendingComptrollerImplementation;\n\n pendingComptrollerImplementation = address(0);\n\n emit NewImplementation(oldImplementation, comptrollerImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingComptrollerImplementation);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public returns (uint) {\n // Check caller = admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n }\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n fallback() external {\n // delegate all other functions to current implementation\n (bool success, ) = comptrollerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/DelegateBorrowers/MoveDebtDelegate.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { approveOrRevert } from \"../lib/approveOrRevert.sol\";\nimport { IVBep20, IComptroller } from \"../InterfacesV8.sol\";\n\ncontract MoveDebtDelegate is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {\n /// @dev VToken return value signalling about successful execution\n uint256 internal constant NO_ERROR = 0;\n\n /// @notice A wildcard indicating that repayment is allowed for _any_ user in the market\n address public constant ANY_USER = address(1);\n\n /// @notice User to borrow on behalf of\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable newBorrower;\n\n /// @notice Whether to allow borrowing from the corresponding vToken\n mapping(address => bool) public borrowAllowed;\n\n /// @notice Whether to allow repaying to the corresponding vToken on behalf of\n /// a certain user. Use ANY_USER to check if repayment is allowed for any user.\n mapping(address => mapping(address => bool)) public repaymentAllowed;\n\n /// @notice Emitted when vToken is allowed or denied to be borrowed from\n event BorrowAllowedSet(address indexed vTokenToBorrow, bool allowed);\n\n /// @notice Emitted when vToken is allowed or denied to be borrowed from\n event RepaymentAllowedSet(address indexed vTokenToRepay, address indexed originalBorrower, bool allowed);\n\n /// @notice Emitted if debt is swapped successfully\n event DebtMoved(\n address indexed originalBorrower,\n address indexed vTokenRepaid,\n uint256 repaidAmount,\n address newBorrower,\n address indexed vTokenBorrowed,\n uint256 borrowedAmount\n );\n\n /// @notice Emitted when the owner transfers tokens, accidentially sent to this contract,\n /// to their account\n event SweptTokens(address indexed token, uint256 amount);\n\n /// @notice Thrown if VTokens' comptrollers are not equal\n error ComptrollerMismatch();\n\n /// @notice Thrown if repayment fails with an error code\n error RepaymentFailed(uint256 errorCode);\n\n /// @notice Thrown if borrow fails with an error code\n error BorrowFailed(uint256 errorCode);\n\n /// @notice Thrown if borrowing from the corresponding vToken is not allowed\n error BorrowNotAllowed(address vToken);\n\n /// @notice Thrown if repaying the debts of the borrower to the corresponding vToken is not allowed\n error RepaymentNotAllowed(address vToken, address borrower);\n\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @param newBorrower_ User to borrow on behalf of\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address newBorrower_) {\n newBorrower = newBorrower_;\n _disableInitializers();\n }\n\n function initialize() external initializer {\n __Ownable2Step_init();\n __ReentrancyGuard_init();\n }\n\n /**\n * @notice Repays originalBorrower's borrow in vTokenToRepay.underlying() and borrows\n * vTokenToBorrow.underlying() on behalf of newBorrower.\n *\n * @param originalBorrower The address of the borrower, whose debt to repay\n * @param vTokenToRepay VToken to repay to on behalf of originalBorrower\n * @param repayAmount The amount to repay in terms of vTokenToRepay.underlying()\n * @param vTokenToBorrow VToken to borrow from\n */\n function moveDebt(\n IVBep20 vTokenToRepay,\n address originalBorrower,\n uint256 repayAmount,\n IVBep20 vTokenToBorrow\n ) external nonReentrant {\n if (!borrowAllowed[address(vTokenToBorrow)]) {\n revert BorrowNotAllowed(address(vTokenToBorrow));\n }\n\n mapping(address => bool) storage repaymentAllowedFor = repaymentAllowed[address(vTokenToRepay)];\n if (!repaymentAllowedFor[ANY_USER] && !repaymentAllowedFor[originalBorrower]) {\n revert RepaymentNotAllowed(address(vTokenToRepay), originalBorrower);\n }\n\n uint256 actualRepaymentAmount = _repay(vTokenToRepay, originalBorrower, repayAmount);\n uint256 amountToBorrow = _convert(vTokenToRepay, vTokenToBorrow, actualRepaymentAmount);\n _borrow(vTokenToBorrow, amountToBorrow);\n emit DebtMoved(\n originalBorrower,\n address(vTokenToRepay),\n actualRepaymentAmount,\n newBorrower,\n address(vTokenToBorrow),\n amountToBorrow\n );\n }\n\n /**\n * @notice Allows or denies borrowing from the corresponding vToken\n * @param vTokenToBorrow VToken to borrow from\n * @param allow Whether to allow borrowing from the corresponding vToken\n */\n function setBorrowAllowed(address vTokenToBorrow, bool allow) external onlyOwner {\n ensureNonzeroAddress(vTokenToBorrow);\n if (borrowAllowed[vTokenToBorrow] != allow) {\n borrowAllowed[vTokenToBorrow] = allow;\n emit BorrowAllowedSet(vTokenToBorrow, allow);\n }\n }\n\n /**\n * @notice Allows or denies repaying the debts of originalBorrower to the corresponding vToken\n * @param vTokenToRepay VToken to repay to\n * @param originalBorrower The address of the borrower, whose debt to repay (or ANY_USER to allow\n * repayments for all users in the market, e.g. if the market is going to be deprecated soon)\n * @param allow Whether to allow repaying to the corresponding vToken on behalf of originalBorrower\n */\n function setRepaymentAllowed(address vTokenToRepay, address originalBorrower, bool allow) external onlyOwner {\n ensureNonzeroAddress(vTokenToRepay);\n ensureNonzeroAddress(originalBorrower);\n if (repaymentAllowed[vTokenToRepay][originalBorrower] != allow) {\n repaymentAllowed[vTokenToRepay][originalBorrower] = allow;\n emit RepaymentAllowedSet(vTokenToRepay, originalBorrower, allow);\n }\n }\n\n /**\n * @notice Transfers tokens, accidentially sent to this contract, to the owner\n * @param token ERC-20 token to sweep\n */\n function sweepTokens(IERC20Upgradeable token) external onlyOwner {\n uint256 amount = token.balanceOf(address(this));\n token.safeTransfer(owner(), amount);\n emit SweptTokens(address(token), amount);\n }\n\n /**\n * @dev Transfers the funds from the sender and repays a borrow in vToken on behalf of the borrower\n * @param vTokenToRepay VToken to repay to\n * @param borrower The address of the borrower, whose debt to repay\n * @param repayAmount The amount to repay in terms of underlying\n */\n function _repay(\n IVBep20 vTokenToRepay,\n address borrower,\n uint256 repayAmount\n ) internal returns (uint256 actualRepaymentAmount) {\n IERC20Upgradeable underlying = IERC20Upgradeable(vTokenToRepay.underlying());\n uint256 balanceBefore = underlying.balanceOf(address(this));\n underlying.safeTransferFrom(msg.sender, address(this), repayAmount);\n uint256 balanceAfter = underlying.balanceOf(address(this));\n uint256 repayAmountMinusFee = balanceAfter - balanceBefore;\n\n uint256 borrowBalanceBefore = vTokenToRepay.borrowBalanceCurrent(borrower);\n approveOrRevert(underlying, address(vTokenToRepay), repayAmountMinusFee);\n uint256 err = vTokenToRepay.repayBorrowBehalf(borrower, repayAmountMinusFee);\n if (err != NO_ERROR) {\n revert RepaymentFailed(err);\n }\n approveOrRevert(underlying, address(vTokenToRepay), 0);\n uint256 borrowBalanceAfter = vTokenToRepay.borrowBalanceCurrent(borrower);\n return borrowBalanceBefore - borrowBalanceAfter;\n }\n\n /**\n * @dev Borrows in vToken on behalf of the borrower and transfers the funds to the sender\n * @param vTokenToBorrow VToken to borrow from\n * @param borrowAmount The amount to borrow in terms of underlying\n */\n function _borrow(IVBep20 vTokenToBorrow, uint256 borrowAmount) internal {\n IERC20Upgradeable underlying = IERC20Upgradeable(vTokenToBorrow.underlying());\n uint256 balanceBefore = underlying.balanceOf(address(this));\n uint256 err = vTokenToBorrow.borrowBehalf(newBorrower, borrowAmount);\n if (err != NO_ERROR) {\n revert BorrowFailed(err);\n }\n uint256 balanceAfter = underlying.balanceOf(address(this));\n uint256 actualBorrowedAmount = balanceAfter - balanceBefore;\n underlying.safeTransfer(msg.sender, actualBorrowedAmount);\n }\n\n /**\n * @dev Converts the value expressed in convertFrom.underlying() to a value\n * in convertTo.underlying(), using the oracle price\n * @param convertFrom VToken to convert from\n * @param convertTo VToken to convert to\n * @param amount The amount in convertFrom.underlying()\n */\n function _convert(IVBep20 convertFrom, IVBep20 convertTo, uint256 amount) internal view returns (uint256) {\n IComptroller comptroller = convertFrom.comptroller();\n if (comptroller != convertTo.comptroller()) {\n revert ComptrollerMismatch();\n }\n ResilientOracleInterface oracle = comptroller.oracle();\n\n // Decimals are accounted for in the oracle contract\n uint256 scaledUsdValue = oracle.getUnderlyingPrice(address(convertFrom)) * amount; // the USD value here has 36 decimals\n return scaledUsdValue / oracle.getUnderlyingPrice(address(convertTo));\n }\n}\n" + }, + "contracts/DelegateBorrowers/SwapDebtDelegate.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\nimport { approveOrRevert } from \"../lib/approveOrRevert.sol\";\nimport { IVBep20, IComptroller } from \"../InterfacesV8.sol\";\n\ncontract SwapDebtDelegate is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {\n /// @dev VToken return value signalling about successful execution\n uint256 internal constant NO_ERROR = 0;\n\n /// @notice Emitted if debt is swapped successfully\n event DebtSwapped(\n address indexed borrower,\n address indexed vTokenRepaid,\n uint256 repaidAmount,\n address indexed vTokenBorrowed,\n uint256 borrowedAmount\n );\n\n /// @notice Emitted when the owner transfers tokens, accidentially sent to this contract,\n /// to their account\n event SweptTokens(address indexed token, uint256 amount);\n\n /// @notice Thrown if VTokens' comptrollers are not equal\n error ComptrollerMismatch();\n\n /// @notice Thrown if repayment fails with an error code\n error RepaymentFailed(uint256 errorCode);\n\n /// @notice Thrown if borrow fails with an error code\n error BorrowFailed(uint256 errorCode);\n\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n function initialize() external initializer {\n __Ownable2Step_init();\n __ReentrancyGuard_init();\n }\n\n /**\n * @notice Repays a borrow in repayTo.underlying() and borrows borrowFrom.underlying()\n * @param borrower The address of the borrower, whose debt to swap\n * @param repayTo VToken to repay the debt to\n * @param borrowFrom VToken to borrow from\n * @param repayAmount The amount to repay in terms of repayTo.underlying()\n */\n function swapDebt(\n address borrower,\n IVBep20 repayTo,\n IVBep20 borrowFrom,\n uint256 repayAmount\n ) external onlyOwner nonReentrant {\n uint256 actualRepaymentAmount = _repay(repayTo, borrower, repayAmount);\n uint256 amountToBorrow = _convert(repayTo, borrowFrom, actualRepaymentAmount);\n _borrow(borrowFrom, borrower, amountToBorrow);\n emit DebtSwapped(borrower, address(repayTo), actualRepaymentAmount, address(borrowFrom), amountToBorrow);\n }\n\n /**\n * @notice Transfers tokens, accidentially sent to this contract, to the owner\n * @param token ERC-20 token to sweep\n */\n function sweepTokens(IERC20Upgradeable token) external onlyOwner {\n uint256 amount = token.balanceOf(address(this));\n token.safeTransfer(owner(), amount);\n emit SweptTokens(address(token), amount);\n }\n\n /**\n * @dev Transfers the funds from the sender and repays a borrow in vToken on behalf of the borrower\n * @param vToken VToken to repay the debt to\n * @param borrower The address of the borrower, whose debt to repay\n * @param repayAmount The amount to repay in terms of underlying\n */\n function _repay(\n IVBep20 vToken,\n address borrower,\n uint256 repayAmount\n ) internal returns (uint256 actualRepaymentAmount) {\n IERC20Upgradeable underlying = IERC20Upgradeable(vToken.underlying());\n uint256 balanceBefore = underlying.balanceOf(address(this));\n underlying.safeTransferFrom(msg.sender, address(this), repayAmount);\n uint256 balanceAfter = underlying.balanceOf(address(this));\n uint256 repayAmountMinusFee = balanceAfter - balanceBefore;\n\n underlying.safeApprove(address(vToken), 0);\n underlying.safeApprove(address(vToken), repayAmountMinusFee);\n uint256 borrowBalanceBefore = vToken.borrowBalanceCurrent(borrower);\n uint256 err = vToken.repayBorrowBehalf(borrower, repayAmountMinusFee);\n if (err != NO_ERROR) {\n revert RepaymentFailed(err);\n }\n uint256 borrowBalanceAfter = vToken.borrowBalanceCurrent(borrower);\n return borrowBalanceBefore - borrowBalanceAfter;\n }\n\n /**\n * @dev Borrows in vToken on behalf of the borrower and transfers the funds to the sender\n * @param vToken VToken to borrow from\n * @param borrower The address of the borrower, who will own the borrow\n * @param borrowAmount The amount to borrow in terms of underlying\n */\n function _borrow(IVBep20 vToken, address borrower, uint256 borrowAmount) internal {\n IERC20Upgradeable underlying = IERC20Upgradeable(vToken.underlying());\n uint256 balanceBefore = underlying.balanceOf(address(this));\n uint256 err = vToken.borrowBehalf(borrower, borrowAmount);\n if (err != NO_ERROR) {\n revert BorrowFailed(err);\n }\n uint256 balanceAfter = underlying.balanceOf(address(this));\n uint256 actualBorrowedAmount = balanceAfter - balanceBefore;\n underlying.safeTransfer(msg.sender, actualBorrowedAmount);\n }\n\n /**\n * @dev Converts the value expressed in convertFrom.underlying() to a value\n * in convertTo.underlying(), using the oracle price\n * @param convertFrom VToken to convert from\n * @param convertTo VToken to convert to\n * @param amount The amount in convertFrom.underlying()\n */\n function _convert(IVBep20 convertFrom, IVBep20 convertTo, uint256 amount) internal view returns (uint256) {\n IComptroller comptroller = convertFrom.comptroller();\n if (comptroller != convertTo.comptroller()) {\n revert ComptrollerMismatch();\n }\n ResilientOracleInterface oracle = comptroller.oracle();\n\n // Decimals are accounted for in the oracle contract\n uint256 scaledUsdValue = oracle.getUnderlyingPrice(address(convertFrom)) * amount; // the USD value here has 36 decimals\n return scaledUsdValue / oracle.getUnderlyingPrice(address(convertTo));\n }\n}\n" + }, + "contracts/external/IProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\ninterface IProtocolShareReserve {\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n ERC4626_WRAPPER_REWARDS,\n FLASHLOAN\n }\n\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\n}\n" + }, + "contracts/external/IWBNB.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\ninterface IWBNB is IERC20Upgradeable {\n function deposit() external payable;\n}\n" + }, + "contracts/FlashLoan/interfaces/IFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { VToken } from \"../../Tokens/VTokens/VToken.sol\";\n\n/// @title IFlashLoanReceiver\n/// @notice Interface for flashLoan receiver contract, which executes custom logic with flash-borrowed assets.\n/// @dev This interface defines the method that must be implemented by any contract wishing to interact with the flashLoan system.\n/// Contracts must ensure they have the means to repay at least the premium (fee), with any unpaid balance becoming debt.\ninterface IFlashLoanReceiver {\n /**\n * @notice Executes an operation after receiving the flash-borrowed assets.\n * @dev Implementation of this function must ensure at least the premium (fee) is repaid within the same transaction.\n * Any unpaid balance (principal + premium - repaid amount) will be added to the onBehalf address's borrow balance.\n * @param vTokens The vToken contracts corresponding to the flash-borrowed underlying assets.\n * @param amounts The amounts of each underlying asset that were flash-borrowed.\n * @param premiums The premiums (fees) associated with each flash-borrowed asset.\n * @param initiator The address that initiated the flash loan.\n * @param onBehalf The address of the user whose debt position will be used for any unpaid flash loan balance.\n * @param param Additional parameters encoded as bytes. These can be used to pass custom data to the receiver contract.\n * @return success True if the operation succeeds (regardless of repayment amount), false if the operation fails.\n * @return repayAmounts Array of uint256 representing the amounts to be repaid for each asset. The receiver contract\n * must approve these amounts to the respective vToken contracts before this function returns.\n */\n function executeOperation(\n VToken[] calldata vTokens,\n uint256[] calldata amounts,\n uint256[] calldata premiums,\n address initiator,\n address onBehalf,\n bytes calldata param\n ) external returns (bool success, uint256[] memory repayAmounts);\n}\n" + }, + "contracts/Governance/TokenRedeemer.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport { Ownable2Step } from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { IVAIController, IVToken, IVBep20, IVBNB } from \"../InterfacesV8.sol\";\nimport { Currency, CurrencyLibrary } from \"../lib/Currency.sol\";\n\ncontract TokenRedeemer is ReentrancyGuard, Ownable2Step {\n using CurrencyLibrary for Currency;\n\n struct Repayment {\n address borrower;\n uint256 amount;\n }\n\n IVBNB public immutable VBNB;\n\n error AccrueInterestFailed(uint256 errCode);\n error RedeemFailed(uint256 errCode);\n error RepaymentFailed(uint256 errCode);\n error NativeTokenTransferFailed();\n\n constructor(address owner_, IVBNB vBNB) {\n ensureNonzeroAddress(owner_);\n VBNB = vBNB;\n _transferOwnership(owner_);\n }\n\n receive() external payable {}\n\n function redeemAndTransfer(IVToken vToken, address destination) external nonReentrant onlyOwner {\n Currency underlying = _underlying(vToken);\n uint256 err = vToken.redeem(vToken.balanceOf(address(this)));\n if (err != 0) {\n revert RedeemFailed(err);\n }\n underlying.transferAll(destination);\n }\n\n function redeemUnderlyingAndTransfer(\n IVToken vToken,\n address destination,\n uint256 amount,\n address receiver\n ) external nonReentrant onlyOwner {\n Currency underlying = _underlying(vToken);\n underlying.transferAll(receiver); // Just in case there were some underlying tokens on the contract\n uint256 err = vToken.redeemUnderlying(amount);\n if (err != 0) {\n revert RedeemFailed(err);\n }\n underlying.transferAll(destination);\n Currency.wrap(address(vToken)).transferAll(receiver);\n }\n\n function redeemUnderlyingAndRepayBorrowBehalf(\n IVToken vToken,\n address borrower,\n uint256 amount,\n address receiver\n ) external nonReentrant onlyOwner {\n Currency underlying = _underlying(vToken);\n\n uint256 err = vToken.redeemUnderlying(amount);\n if (err != 0) {\n revert RedeemFailed(err);\n }\n\n underlying.approve(address(vToken), amount);\n\n _repay(vToken, borrower, amount);\n\n underlying.approve(address(vToken), 0);\n\n underlying.transferAll(receiver);\n Currency.wrap(address(vToken)).transferAll(receiver);\n }\n\n function redeemAndBatchRepay(\n IVToken vToken,\n Repayment[] calldata requestedRepayments,\n address receiver\n ) external nonReentrant onlyOwner {\n _accrueInterest(vToken);\n\n (uint256 totalBorrowedAmount, Repayment[] memory repayments) = _getAmountsToRepay(vToken, requestedRepayments);\n _redeemUpTo(vToken, totalBorrowedAmount);\n\n Currency underlying = _underlying(vToken);\n uint256 balance = underlying.balanceOfSelf();\n underlying.approve(address(vToken), totalBorrowedAmount);\n uint256 repaymentsCount = repayments.length;\n // The code below assumes no fees on transfer\n if (balance >= totalBorrowedAmount) {\n // If we're doing a full repayment, we can optimize it by skipping the balance checks\n for (uint256 i = 0; i < repaymentsCount; ++i) {\n Repayment memory repayment = repayments[i];\n _repay(vToken, repayment.borrower, repayment.amount);\n }\n } else {\n // Otherwise, we have to check and update the balance on every iteration\n for (uint256 i = 0; i < repaymentsCount && balance != 0; ++i) {\n Repayment memory repayment = repayments[i];\n _repay(vToken, repayment.borrower, _min(repayment.amount, balance));\n balance = underlying.balanceOfSelf();\n }\n }\n underlying.approve(address(vToken), 0);\n\n underlying.transferAll(receiver);\n Currency.wrap(address(vToken)).transferAll(receiver);\n }\n\n function batchRepayVAI(\n IVAIController vaiController,\n Repayment[] calldata requestedRepayments,\n address receiver\n ) external nonReentrant onlyOwner {\n vaiController.accrueVAIInterest();\n Currency vai = Currency.wrap(vaiController.getVAIAddress());\n uint256 balance = vai.balanceOfSelf();\n vai.approve(address(vaiController), type(uint256).max);\n uint256 repaymentsCount = requestedRepayments.length;\n for (uint256 i = 0; i < repaymentsCount && balance != 0; ++i) {\n Repayment calldata requestedRepayment = requestedRepayments[i];\n uint256 repaymentCap = requestedRepayment.amount;\n uint256 debt = vaiController.getVAIRepayAmount(requestedRepayment.borrower);\n uint256 amount = _min(repaymentCap, debt);\n _repayVAI(vaiController, requestedRepayment.borrower, _min(amount, balance));\n balance = vai.balanceOfSelf();\n }\n vai.approve(address(vaiController), 0);\n vai.transferAll(receiver);\n }\n\n function sweepTokens(address token, address destination) external onlyOwner {\n Currency.wrap(token).transferAll(destination);\n }\n\n function _accrueInterest(IVToken vToken) internal {\n uint256 err = vToken.accrueInterest();\n if (err != 0) {\n revert AccrueInterestFailed(err);\n }\n }\n\n function _redeemUpTo(IVToken vToken, uint256 amount) internal {\n uint256 unredeemedUnderlying = vToken.balanceOfUnderlying(address(this));\n if (unredeemedUnderlying > 0) {\n uint256 err = vToken.redeemUnderlying(_min(amount, unredeemedUnderlying));\n if (err != 0) {\n revert RedeemFailed(err);\n }\n }\n }\n\n function _repay(IVToken vToken, address borrower, uint256 amount) internal {\n if (amount == 0) {\n return;\n }\n if (_isVBNB(vToken)) {\n IVBNB(address(vToken)).repayBorrowBehalf{ value: amount }(borrower);\n } else {\n uint256 err = IVBep20(address(vToken)).repayBorrowBehalf(borrower, amount);\n if (err != 0) {\n revert RepaymentFailed(err);\n }\n }\n }\n\n function _repayVAI(IVAIController vaiController, address borrower, uint256 amount) internal {\n if (amount == 0) {\n return;\n }\n (uint256 err, ) = vaiController.repayVAIBehalf(borrower, amount);\n if (err != 0) {\n revert RepaymentFailed(err);\n }\n }\n\n function _getAmountsToRepay(\n IVToken vToken,\n Repayment[] calldata requestedRepayments\n ) internal view returns (uint256, Repayment[] memory) {\n uint256 repaymentsCount = requestedRepayments.length;\n Repayment[] memory actualRepayments = new Repayment[](repaymentsCount);\n uint256 totalAmountToRepay = 0;\n for (uint256 i = 0; i < repaymentsCount; ++i) {\n Repayment calldata requestedRepayment = requestedRepayments[i];\n uint256 repaymentCap = requestedRepayment.amount;\n uint256 debt = vToken.borrowBalanceStored(requestedRepayment.borrower);\n uint256 amountToRepay = _min(repaymentCap, debt);\n totalAmountToRepay += amountToRepay;\n actualRepayments[i] = Repayment({ borrower: requestedRepayment.borrower, amount: amountToRepay });\n }\n return (totalAmountToRepay, actualRepayments);\n }\n\n function _underlying(IVToken vToken) internal view returns (Currency) {\n if (_isVBNB(vToken)) {\n return CurrencyLibrary.NATIVE;\n }\n return Currency.wrap(IVBep20(address(vToken)).underlying());\n }\n\n function _isVBNB(IVToken vToken) internal view returns (bool) {\n return address(vToken) == address(VBNB);\n }\n\n function _min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n}\n" + }, + "contracts/Governance/VTreasuryV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { SafeERC20, IERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { Ownable2Step } from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport { ReentrancyGuard } from \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\n\n/**\n * @title VTreasuryV8\n * @author Venus\n * @notice Protocol treasury that holds tokens owned by Venus\n */\ncontract VTreasuryV8 is Ownable2Step, ReentrancyGuard {\n using SafeERC20 for IERC20;\n\n // WithdrawTreasuryToken Event\n event WithdrawTreasuryToken(address indexed tokenAddress, uint256 withdrawAmount, address indexed withdrawAddress);\n\n // WithdrawTreasuryNative Event\n event WithdrawTreasuryNative(uint256 withdrawAmount, address indexed withdrawAddress);\n\n /// @notice Thrown if the supplied address is a zero address where it is not allowed\n error ZeroAddressNotAllowed();\n\n /**\n * @notice To receive Native when msg.data is not empty\n */\n fallback() external payable {}\n\n /**\n * @notice To receive Native when msg.data is empty\n */\n receive() external payable {}\n\n /**\n * @notice Withdraw Treasury Tokens, Only owner call it\n * @param tokenAddress The address of treasury token\n * @param withdrawAmount The withdraw amount to owner\n * @param withdrawAddress The withdraw address\n * @custom:error ZeroAddressNotAllowed thrown when token or withdrawAddress is zero.\n */\n function withdrawTreasuryToken(\n address tokenAddress,\n uint256 withdrawAmount,\n address withdrawAddress\n ) external onlyOwner nonReentrant {\n ensureNonzeroAddress(tokenAddress);\n ensureNonzeroAddress(withdrawAddress);\n require(withdrawAmount > 0, \"withdrawAmount must not be zero\");\n\n uint256 actualWithdrawAmount = withdrawAmount;\n // Get Treasury Token Balance\n uint256 treasuryBalance = IERC20(tokenAddress).balanceOf(address(this));\n\n // Check Withdraw Amount\n if (withdrawAmount > treasuryBalance) {\n // Update actualWithdrawAmount\n actualWithdrawAmount = treasuryBalance;\n }\n\n // Transfer Token to withdrawAddress\n IERC20(tokenAddress).safeTransfer(withdrawAddress, actualWithdrawAmount);\n\n emit WithdrawTreasuryToken(tokenAddress, actualWithdrawAmount, withdrawAddress);\n }\n\n /**\n * @notice Withdraw Treasury Native, Only owner call it\n * @param withdrawAmount The withdraw amount to owner\n * @param withdrawAddress The withdraw address\n * @custom:error ZeroAddressNotAllowed thrown when withdrawAddress is zero.\n */\n function withdrawTreasuryNative(\n uint256 withdrawAmount,\n address payable withdrawAddress\n ) external payable onlyOwner nonReentrant {\n ensureNonzeroAddress(withdrawAddress);\n require(withdrawAmount > 0, \"withdrawAmount must not be zero\");\n uint256 actualWithdrawAmount = withdrawAmount;\n // Get Treasury Native Balance\n uint256 nativeBalance = address(this).balance;\n\n // Check Withdraw Amount\n if (withdrawAmount > nativeBalance) {\n // Update actualWithdrawAmount\n actualWithdrawAmount = nativeBalance;\n }\n // Transfer the native token to withdrawAddress\n (bool sent, ) = withdrawAddress.call{ value: actualWithdrawAmount }(\"\");\n require(sent, \"Call failed\");\n emit WithdrawTreasuryNative(actualWithdrawAmount, withdrawAddress);\n }\n\n /// @notice Checks if the provided address is nonzero, reverts otherwise\n /// @param address_ Address to check\n /// @custom:error ZeroAddressNotAllowed is thrown if the provided address is a zero address\n function ensureNonzeroAddress(address address_) internal pure {\n if (address_ == address(0)) {\n revert ZeroAddressNotAllowed();\n }\n }\n}\n" + }, + "contracts/hardhat-dependency-compiler/hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport 'hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol';\n" + }, + "contracts/hardhat-dependency-compiler/hardhat-deploy/solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: UNLICENSED\npragma solidity >0.0.0;\nimport 'hardhat-deploy/solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol';\n" + }, + "contracts/InterestRateModels/InterestRateModelV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Venus's InterestRateModelV8 Interface\n * @author Venus\n */\nabstract contract InterestRateModelV8 {\n /// @notice Indicator that this is an InterestRateModel contract (for inspection)\n bool public constant isInterestRateModel = true;\n\n /**\n * @notice Calculates the current borrow interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amnount of reserves the market has\n * @return The borrow rate per block (as a percentage, and scaled by 1e18)\n */\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view virtual returns (uint256);\n\n /**\n * @notice Calculates the current supply interest rate per block\n * @param cash The total amount of cash the market has\n * @param borrows The total amount of borrows the market has outstanding\n * @param reserves The total amnount of reserves the market has\n * @param reserveFactorMantissa The current reserve factor the market has\n * @return The supply rate per block (as a percentage, and scaled by 1e18)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa\n ) external view virtual returns (uint256);\n}\n" + }, + "contracts/InterestRateModels/TwoKinksInterestRateModel.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { InterestRateModelV8 } from \"./InterestRateModelV8.sol\";\n\n/**\n * @title TwoKinksInterestRateModel\n * @author Venus\n * @notice An interest rate model with two different slope increase or decrease each after a certain utilization threshold called **kink** is reached.\n */\ncontract TwoKinksInterestRateModel is InterestRateModelV8 {\n int256 public immutable BLOCKS_PER_YEAR;\n\n ////////////////////// SLOPE 1 //////////////////////\n\n /**\n * @notice The multiplier of utilization rate per block that gives the slope 1 of the interest rate scaled by EXP_SCALE\n */\n int256 public immutable MULTIPLIER_PER_BLOCK;\n\n /**\n * @notice The base interest rate per block which is the y-intercept when utilization rate is 0 scaled by EXP_SCALE\n */\n int256 public immutable BASE_RATE_PER_BLOCK;\n\n ////////////////////// SLOPE 2 //////////////////////\n\n /**\n * @notice The utilization point at which the multiplier2 is applied\n */\n int256 public immutable KINK_1;\n\n /**\n * @notice The multiplier of utilization rate per block that gives the slope 2 of the interest rate scaled by EXP_SCALE\n */\n int256 public immutable MULTIPLIER_2_PER_BLOCK;\n\n /**\n * @notice The base interest rate per block which is the y-intercept when utilization rate hits KINK_1 scaled by EXP_SCALE\n */\n int256 public immutable BASE_RATE_2_PER_BLOCK;\n\n /**\n * @notice The maximum kink interest rate scaled by EXP_SCALE\n */\n int256 public immutable RATE_1;\n\n ////////////////////// SLOPE 3 //////////////////////\n\n /**\n * @notice The utilization point at which the jump multiplier is applied\n */\n int256 public immutable KINK_2;\n\n /**\n * @notice The multiplier of utilization rate per block that gives the slope 3 of interest rate scaled by EXP_SCALE\n */\n int256 public immutable JUMP_MULTIPLIER_PER_BLOCK;\n\n /**\n * @notice The maximum kink interest rate scaled by EXP_SCALE\n */\n int256 public immutable RATE_2;\n\n /// @notice Base unit for computations, usually used in scaling (multiplications, divisions)\n uint256 internal constant EXP_SCALE = 1e18;\n\n /**\n * @notice Thrown when a negative value is not allowed\n */\n error NegativeValueNotAllowed();\n\n /**\n * @notice Thrown when the kink points are not in the correct order\n */\n error InvalidKink();\n\n /**\n * @notice Construct an interest rate model\n * @param baseRatePerYear_ The approximate target base APR, as a mantissa (scaled by EXP_SCALE)\n * @param multiplierPerYear_ The rate of increase or decrease in interest rate wrt utilization (scaled by EXP_SCALE)\n * @param kink1_ The utilization point at which the multiplier2 is applied\n * @param multiplier2PerYear_ The rate of increase or decrease in interest rate wrt utilization after hitting KINK_1 (scaled by EXP_SCALE)\n * @param baseRate2PerYear_ The additional base APR after hitting KINK_1, as a mantissa (scaled by EXP_SCALE)\n * @param kink2_ The utilization point at which the jump multiplier is applied\n * @param jumpMultiplierPerYear_ The multiplier after hitting KINK_2\n * @param blocksPerYear_ The approximate number of blocks per year to assume\n */\n constructor(\n int256 baseRatePerYear_,\n int256 multiplierPerYear_,\n int256 kink1_,\n int256 multiplier2PerYear_,\n int256 baseRate2PerYear_,\n int256 kink2_,\n int256 jumpMultiplierPerYear_,\n int256 blocksPerYear_\n ) {\n if (baseRatePerYear_ < 0 || baseRate2PerYear_ < 0) {\n revert NegativeValueNotAllowed();\n }\n\n if (kink2_ <= kink1_ || kink1_ <= 0) {\n revert InvalidKink();\n }\n\n BLOCKS_PER_YEAR = blocksPerYear_;\n BASE_RATE_PER_BLOCK = baseRatePerYear_ / BLOCKS_PER_YEAR;\n MULTIPLIER_PER_BLOCK = multiplierPerYear_ / BLOCKS_PER_YEAR;\n KINK_1 = kink1_;\n MULTIPLIER_2_PER_BLOCK = multiplier2PerYear_ / BLOCKS_PER_YEAR;\n BASE_RATE_2_PER_BLOCK = baseRate2PerYear_ / BLOCKS_PER_YEAR;\n KINK_2 = kink2_;\n JUMP_MULTIPLIER_PER_BLOCK = jumpMultiplierPerYear_ / BLOCKS_PER_YEAR;\n\n int256 expScale = int256(EXP_SCALE);\n RATE_1 = (((KINK_1 * MULTIPLIER_PER_BLOCK) / expScale) + BASE_RATE_PER_BLOCK);\n\n int256 slope2Util;\n unchecked {\n slope2Util = KINK_2 - KINK_1;\n }\n RATE_2 = ((slope2Util * MULTIPLIER_2_PER_BLOCK) / expScale) + BASE_RATE_2_PER_BLOCK;\n }\n\n /**\n * @notice Calculates the current borrow rate per slot (block)\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @return The borrow rate percentage per slot (block) as a mantissa (scaled by EXP_SCALE)\n */\n function getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) external view override returns (uint256) {\n return _getBorrowRate(cash, borrows, reserves);\n }\n\n /**\n * @notice Calculates the current supply rate per slot (block)\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @param reserveFactorMantissa The current reserve factor for the market\n * @return The supply rate percentage per slot (block) as a mantissa (scaled by EXP_SCALE)\n */\n function getSupplyRate(\n uint256 cash,\n uint256 borrows,\n uint256 reserves,\n uint256 reserveFactorMantissa\n ) public view virtual override returns (uint256) {\n uint256 oneMinusReserveFactor = EXP_SCALE - reserveFactorMantissa;\n uint256 borrowRate = _getBorrowRate(cash, borrows, reserves);\n uint256 rateToPool = (borrowRate * oneMinusReserveFactor) / EXP_SCALE;\n return (utilizationRate(cash, borrows, reserves) * rateToPool) / EXP_SCALE;\n }\n\n /**\n * @notice Calculates the utilization rate of the market: `borrows / (cash + borrows - reserves)`\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @return The utilization rate as a mantissa between [0, EXP_SCALE]\n */\n function utilizationRate(uint256 cash, uint256 borrows, uint256 reserves) public pure returns (uint256) {\n // Utilization rate is 0 when there are no borrows\n if (borrows == 0) {\n return 0;\n }\n\n uint256 rate = (borrows * EXP_SCALE) / (cash + borrows - reserves);\n\n if (rate > EXP_SCALE) {\n rate = EXP_SCALE;\n }\n\n return rate;\n }\n\n /**\n * @notice Calculates the current borrow rate per slot (block), with the error code expected by the market\n * @param cash The amount of cash in the market\n * @param borrows The amount of borrows in the market\n * @param reserves The amount of reserves in the market\n * @return The borrow rate percentage per slot (block) as a mantissa (scaled by EXP_SCALE)\n */\n function _getBorrowRate(uint256 cash, uint256 borrows, uint256 reserves) internal view returns (uint256) {\n int256 util = int256(utilizationRate(cash, borrows, reserves));\n int256 expScale = int256(EXP_SCALE);\n\n if (util < KINK_1) {\n return _minCap(((util * MULTIPLIER_PER_BLOCK) / expScale) + BASE_RATE_PER_BLOCK);\n } else if (util < KINK_2) {\n int256 slope2Util;\n unchecked {\n slope2Util = util - KINK_1;\n }\n int256 rate2 = ((slope2Util * MULTIPLIER_2_PER_BLOCK) / expScale) + BASE_RATE_2_PER_BLOCK;\n\n return _minCap(RATE_1 + rate2);\n } else {\n int256 slope3Util;\n unchecked {\n slope3Util = util - KINK_2;\n }\n int256 rate3 = ((slope3Util * JUMP_MULTIPLIER_PER_BLOCK) / expScale);\n\n return _minCap(RATE_1 + RATE_2 + rate3);\n }\n }\n\n /**\n * @notice Returns 0 if number is less than 0, otherwise returns the input\n * @param number The first number\n * @return The maximum of 0 and input number\n */\n function _minCap(int256 number) internal pure returns (uint256) {\n int256 zero;\n return uint256(number > zero ? number : zero);\n }\n}\n" + }, + "contracts/InterfacesV8.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\ninterface IVToken is IERC20Upgradeable {\n function accrueInterest() external returns (uint256);\n\n function redeem(uint256 redeemTokens) external returns (uint256);\n\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256);\n\n function borrowBalanceCurrent(address borrower) external returns (uint256);\n\n function balanceOfUnderlying(address owner) external returns (uint256);\n\n function comptroller() external view returns (IComptroller);\n\n function borrowBalanceStored(address account) external view returns (uint256);\n}\n\ninterface IVBep20 is IVToken {\n function borrowBehalf(address borrower, uint256 borrowAmount) external returns (uint256);\n\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256);\n\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n IVToken vTokenCollateral\n ) external returns (uint256);\n\n function underlying() external view returns (address);\n}\n\ninterface IVBNB is IVToken {\n function repayBorrowBehalf(address borrower) external payable;\n\n function liquidateBorrow(address borrower, IVToken vTokenCollateral) external payable;\n}\n\ninterface IVAIController {\n function accrueVAIInterest() external;\n\n function liquidateVAI(\n address borrower,\n uint256 repayAmount,\n IVToken vTokenCollateral\n ) external returns (uint256, uint256);\n\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\n\n function getVAIAddress() external view returns (address);\n\n function getVAIRepayAmount(address borrower) external view returns (uint256);\n}\n\ninterface IComptroller {\n enum Action {\n MINT,\n REDEEM,\n BORROW,\n REPAY,\n SEIZE,\n LIQUIDATE,\n TRANSFER,\n ENTER_MARKET,\n EXIT_MARKET\n }\n\n function _setActionsPaused(address[] calldata markets_, Action[] calldata actions_, bool paused_) external;\n\n function vaiController() external view returns (IVAIController);\n\n function liquidatorContract() external view returns (address);\n\n function oracle() external view returns (ResilientOracleInterface);\n\n function actionPaused(address market, Action action) external view returns (bool);\n\n function markets(address) external view returns (bool, uint256, bool);\n\n function isForcedLiquidationEnabled(address) external view returns (bool);\n\n function getEffectiveLiquidationIncentive(address account, address vToken) external view returns (uint256);\n}\n\ninterface ILiquidator {\n function restrictLiquidation(address borrower) external;\n\n function unrestrictLiquidation(address borrower) external;\n\n function addToAllowlist(address borrower, address liquidator) external;\n\n function removeFromAllowlist(address borrower, address liquidator) external;\n\n function liquidateBorrow(\n address vToken,\n address borrower,\n uint256 repayAmount,\n IVToken vTokenCollateral\n ) external payable;\n\n function setTreasuryPercent(uint256 newTreasuryPercentMantissa) external;\n\n function treasuryPercentMantissa() external view returns (uint256);\n}\n" + }, + "contracts/Lens/ComptrollerLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { ExponentialNoError } from \"../Utils/ExponentialNoError.sol\";\nimport { ComptrollerErrorReporter } from \"../Utils/ErrorReporter.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { ComptrollerLensInterface } from \"../Comptroller/ComptrollerLensInterface.sol\";\nimport { VAIControllerInterface } from \"../Tokens/VAI/VAIControllerInterface.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\nimport { WeightFunction } from \"../Comptroller/Diamond/interfaces/IFacetBase.sol\";\n\n/**\n * @title ComptrollerLens Contract\n * @author Venus\n * @notice The ComptrollerLens contract has functions to get the number of tokens that\n * can be seized through liquidation, hypothetical account liquidity and shortfall of an account.\n */\ncontract ComptrollerLens is ComptrollerLensInterface, ComptrollerErrorReporter, ExponentialNoError {\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account liquidity.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountLiquidityLocalVars {\n uint sumCollateral;\n uint sumBorrowPlusEffects;\n uint vTokenBalance;\n uint borrowBalance;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp weightedFactor;\n Exp exchangeRate;\n Exp tokensToDenom;\n Exp collateralPrice;\n Exp debtPrice;\n IDeviationBoundedOracle boundedOracle;\n ResilientOracleInterface spotOracle;\n }\n\n /**\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\n * @dev This will be used only in vBNB\n * @param comptroller Address of comptroller\n * @param vTokenBorrowed Address of the borrowed vToken\n * @param vTokenCollateral Address of collateral for the borrow\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\n * @return A tuple of error code, and tokens to seize\n */\n function liquidateCalculateSeizeTokens(\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\n\n uint seizeTokens = _calculateSeizeTokens(\n actualRepayAmount,\n liquidationIncentiveMantissa,\n priceBorrowedMantissa,\n priceCollateralMantissa,\n exchangeRateMantissa\n );\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /**\n * @notice Computes the number of collateral tokens to be seized in a liquidation event\n * @param borrower Address of borrower whose collateral is being seized\n * @param comptroller Address of comptroller\n * @param vTokenBorrowed Address of the borrowed vToken\n * @param vTokenCollateral Address of collateral for the borrow\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of total borrowed amount\n * @return A tuple of error code, and tokens to seize\n */\n function liquidateCalculateSeizeTokens(\n address borrower,\n address comptroller,\n address vTokenBorrowed,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenBorrowed);\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\n if (priceBorrowedMantissa == 0 || priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getEffectiveLiquidationIncentive(\n borrower,\n vTokenCollateral\n );\n\n uint seizeTokens = _calculateSeizeTokens(\n actualRepayAmount,\n liquidationIncentiveMantissa,\n priceBorrowedMantissa,\n priceCollateralMantissa,\n exchangeRateMantissa\n );\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /**\n * @notice Computes the number of VAI tokens to be seized in a liquidation event\n * @param comptroller Address of comptroller\n * @param vTokenCollateral Address of collateral for vToken\n * @param actualRepayAmount Repayment amount i.e amount to be repaid of the total borrowed amount\n * @return A tuple of error code, and tokens to seize\n */\n function liquidateVAICalculateSeizeTokens(\n address comptroller,\n address vTokenCollateral,\n uint actualRepayAmount\n ) external view returns (uint, uint) {\n /* Read oracle prices for borrowed and collateral markets */\n uint priceBorrowedMantissa = 1e18; // Note: this is VAI\n uint priceCollateralMantissa = ComptrollerInterface(comptroller).oracle().getUnderlyingPrice(vTokenCollateral);\n if (priceCollateralMantissa == 0) {\n return (uint(Error.PRICE_ERROR), 0);\n }\n\n /*\n * Get the exchange rate and calculate the number of collateral tokens to seize:\n * seizeAmount = actualRepayAmount * liquidationIncentive * priceBorrowed / priceCollateral\n * seizeTokens = seizeAmount / exchangeRate\n * = actualRepayAmount * (liquidationIncentive * priceBorrowed) / (priceCollateral * exchangeRate)\n */\n uint exchangeRateMantissa = VToken(vTokenCollateral).exchangeRateStored(); // Note: reverts on error\n uint liquidationIncentiveMantissa = ComptrollerInterface(comptroller).getLiquidationIncentive(vTokenCollateral);\n uint seizeTokens = _calculateSeizeTokens(\n actualRepayAmount,\n liquidationIncentiveMantissa,\n priceBorrowedMantissa,\n priceCollateralMantissa,\n exchangeRateMantissa\n );\n\n return (uint(Error.NO_ERROR), seizeTokens);\n }\n\n /**\n * @notice Computes the hypothetical liquidity and shortfall of an account given a hypothetical borrow\n * A snapshot of the account is taken and the total borrow amount of the account is calculated\n * @param comptroller Address of comptroller\n * @param account Address of the borrowed vToken\n * @param vTokenModify Address of collateral for vToken\n * @param redeemTokens Number of vTokens being redeemed\n * @param borrowAmount Amount borrowed\n * @param weightingStrategy The weighting strategy to use:\n * - `WeightFunction.USE_COLLATERAL_FACTOR` to use collateral factor\n * - `WeightFunction.USE_LIQUIDATION_THRESHOLD` to use liquidation threshold\n * @return Returns a tuple of error code, liquidity, and shortfall\n */\n function getHypotheticalAccountLiquidity(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount,\n WeightFunction weightingStrategy\n ) external view returns (uint, uint, uint) {\n (uint errorCode, AccountLiquidityLocalVars memory vars) = _calculateAccountPosition(\n comptroller,\n account,\n vTokenModify,\n redeemTokens,\n borrowAmount,\n weightingStrategy\n );\n if (errorCode != 0) {\n return (errorCode, 0, 0);\n }\n\n // These are safe, as the underflow condition is checked first\n if (vars.sumCollateral > vars.sumBorrowPlusEffects) {\n return (uint(Error.NO_ERROR), vars.sumCollateral - vars.sumBorrowPlusEffects, 0);\n } else {\n return (uint(Error.NO_ERROR), 0, vars.sumBorrowPlusEffects - vars.sumCollateral);\n }\n }\n\n /**\n * @notice Computes an account's aggregate weighted-collateral and total-borrow values,\n * optionally applying hypothetical redeem/borrow effects on a single market.\n * @dev Pricing differs by weighting strategy:\n * - USE_COLLATERAL_FACTOR: collateral is valued at `DeviationBoundedOracle.getBoundedCollateralPriceView`,\n * borrows at `getBoundedDebtPriceView`.\n * - USE_LIQUIDATION_THRESHOLD: both collateral and borrows use the spot oracle price.\n * VAI borrows (from `vaiController.getVAIRepayAmount`) are added to `sumBorrowPlusEffects` after\n * the per-asset loop, regardless of weighting strategy.\n * @param comptroller Address of the comptroller whose markets and oracle are used\n * @param account Address of the account whose position is being computed\n * @param vTokenModify Market to apply hypothetical effects on; pass `VToken(address(0))` for none\n * @param redeemTokens Number of vTokens hypothetically redeemed from `vTokenModify`\n * @param borrowAmount Amount of underlying hypothetically borrowed from `vTokenModify`\n * @param weightingStrategy USE_COLLATERAL_FACTOR for borrow/entry checks; USE_LIQUIDATION_THRESHOLD for liquidation checks\n * @return oErr 0 on success, or a non-zero `Error` code (SNAPSHOT_ERROR or PRICE_ERROR) on failure\n * @return vars Accumulated position data; `sumCollateral` and `sumBorrowPlusEffects` are the primary outputs\n */\n function _calculateAccountPosition(\n address comptroller,\n address account,\n VToken vTokenModify,\n uint redeemTokens,\n uint borrowAmount,\n WeightFunction weightingStrategy\n ) internal view returns (uint oErr, AccountLiquidityLocalVars memory vars) {\n // For each asset the account is in\n VToken[] memory assets = ComptrollerInterface(comptroller).getAssetsIn(account);\n uint assetsCount = assets.length;\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\n vars.boundedOracle = ComptrollerInterface(comptroller).deviationBoundedOracle();\n } else {\n vars.spotOracle = ComptrollerInterface(comptroller).oracle();\n }\n for (uint i = 0; i < assetsCount; ++i) {\n VToken asset = assets[i];\n\n // Read the balances and exchange rate from the vToken\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = asset.getAccountSnapshot(\n account\n );\n if (oErr != 0) {\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\n return (uint(Error.SNAPSHOT_ERROR), vars);\n }\n vars.weightedFactor = Exp({\n mantissa: ComptrollerInterface(comptroller).getEffectiveLtvFactor(\n account,\n address(asset),\n weightingStrategy\n )\n });\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n // Determine bounded prices for CF path\n if (weightingStrategy == WeightFunction.USE_COLLATERAL_FACTOR) {\n (uint256 collateralPriceMantissa, uint256 debtPriceMantissa) = vars.boundedOracle.getBoundedPricesView(\n address(asset)\n );\n if (collateralPriceMantissa == 0 || debtPriceMantissa == 0) {\n return (uint(Error.PRICE_ERROR), vars);\n }\n vars.collateralPrice = Exp({ mantissa: collateralPriceMantissa });\n vars.debtPrice = Exp({ mantissa: debtPriceMantissa });\n } else {\n // LT path — always spot\n vars.oraclePriceMantissa = vars.spotOracle.getUnderlyingPrice(address(asset));\n if (vars.oraclePriceMantissa == 0) {\n return (uint(Error.PRICE_ERROR), vars);\n }\n vars.collateralPrice = Exp({ mantissa: vars.oraclePriceMantissa });\n vars.debtPrice = Exp({ mantissa: vars.oraclePriceMantissa });\n }\n\n // Pre-compute a conversion factor from tokens -> bnb (normalized price value)\n vars.tokensToDenom = mul_(mul_(vars.weightedFactor, vars.exchangeRate), vars.collateralPrice);\n\n // sumCollateral += tokensToDenom * vTokenBalance\n vars.sumCollateral = mul_ScalarTruncateAddUInt(vars.tokensToDenom, vars.vTokenBalance, vars.sumCollateral);\n\n // sumBorrowPlusEffects += debtPrice * borrowBalance\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.debtPrice,\n vars.borrowBalance,\n vars.sumBorrowPlusEffects\n );\n\n // Calculate effects of interacting with vTokenModify\n if (asset == vTokenModify) {\n // redeem effect — uses collateral-bounded tokensToDenom\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.tokensToDenom,\n redeemTokens,\n vars.sumBorrowPlusEffects\n );\n\n // borrow effect — uses debt-bounded price\n vars.sumBorrowPlusEffects = mul_ScalarTruncateAddUInt(\n vars.debtPrice,\n borrowAmount,\n vars.sumBorrowPlusEffects\n );\n }\n }\n\n VAIControllerInterface vaiController = ComptrollerInterface(comptroller).vaiController();\n\n if (address(vaiController) != address(0)) {\n vars.sumBorrowPlusEffects = add_(vars.sumBorrowPlusEffects, vaiController.getVAIRepayAmount(account));\n }\n oErr = uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Calculate the number of tokens to seize during liquidation\n * @param actualRepayAmount The amount of debt being repaid in the liquidation\n * @param liquidationIncentiveMantissa The liquidation incentive, scaled by 1e18\n * @param priceBorrowedMantissa The price of the borrowed asset, scaled by 1e18\n * @param priceCollateralMantissa The price of the collateral asset, scaled by 1e18\n * @param exchangeRateMantissa The exchange rate of the collateral asset, scaled by 1e18\n * @return seizeTokens The number of tokens to seize during liquidation, scaled by 1e18\n */\n function _calculateSeizeTokens(\n uint actualRepayAmount,\n uint liquidationIncentiveMantissa,\n uint priceBorrowedMantissa,\n uint priceCollateralMantissa,\n uint exchangeRateMantissa\n ) internal pure returns (uint seizeTokens) {\n Exp memory numerator = mul_(\n Exp({ mantissa: liquidationIncentiveMantissa }),\n Exp({ mantissa: priceBorrowedMantissa })\n );\n Exp memory denominator = mul_(\n Exp({ mantissa: priceCollateralMantissa }),\n Exp({ mantissa: exchangeRateMantissa })\n );\n\n seizeTokens = mul_ScalarTruncate(div_(numerator, denominator), actualRepayAmount);\n }\n}\n" + }, + "contracts/Lens/SnapshotLens.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { ExponentialNoError } from \"../Utils/ExponentialNoError.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VBep20 } from \"../Tokens/VTokens/VBep20.sol\";\nimport { WeightFunction } from \"../Comptroller/Diamond/interfaces/IFacetBase.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\n\ncontract SnapshotLens is ExponentialNoError {\n struct AccountSnapshot {\n address account;\n string assetName;\n address vTokenAddress;\n address underlyingAssetAddress;\n uint256 supply;\n uint256 supplyInUsd;\n uint256 collateral;\n uint256 borrows;\n uint256 borrowsInUsd;\n uint256 spotPrice;\n uint256 boundedCollateralPrice;\n uint256 boundedDebtPrice;\n uint256 accruedInterest;\n uint vTokenDecimals;\n uint underlyingDecimals;\n uint exchangeRate;\n bool isACollateral;\n }\n\n /** Snapshot calculation **/\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account snapshot.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountSnapshotLocalVars {\n uint collateral;\n uint vTokenBalance;\n uint borrowBalance;\n uint borrowsInUsd;\n uint balanceOfUnderlying;\n uint supplyInUsd;\n uint exchangeRateMantissa;\n uint oraclePriceMantissa;\n Exp collateralFactor;\n Exp exchangeRate;\n Exp oraclePrice;\n Exp tokensToDenom;\n bool isACollateral;\n }\n\n function getAccountSnapshot(\n address payable account,\n address comptrollerAddress\n ) public returns (AccountSnapshot[] memory) {\n // For each asset the account is in\n VToken[] memory assets = ComptrollerInterface(comptrollerAddress).getAllMarkets();\n AccountSnapshot[] memory accountSnapshots = new AccountSnapshot[](assets.length);\n for (uint256 i = 0; i < assets.length; ++i) {\n accountSnapshots[i] = getAccountSnapshot(account, comptrollerAddress, assets[i]);\n }\n return accountSnapshots;\n }\n\n function isACollateral(address account, address asset, address comptrollerAddress) public view returns (bool) {\n VToken[] memory assetsAsCollateral = ComptrollerInterface(comptrollerAddress).getAssetsIn(account);\n for (uint256 j = 0; j < assetsAsCollateral.length; ++j) {\n if (address(assetsAsCollateral[j]) == asset) {\n return true;\n }\n }\n\n return false;\n }\n\n function getAccountSnapshot(\n address payable account,\n address comptrollerAddress,\n VToken vToken\n ) public returns (AccountSnapshot memory) {\n AccountSnapshotLocalVars memory vars; // Holds all our calculation results\n uint oErr;\n\n // Read the balances and exchange rate from the vToken\n (oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = vToken.getAccountSnapshot(account);\n require(oErr == 0, \"Snapshot Error\");\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n uint collateralFactorMantissa = ComptrollerInterface(comptrollerAddress).getEffectiveLtvFactor(\n account,\n address(vToken),\n WeightFunction.USE_COLLATERAL_FACTOR\n );\n vars.collateralFactor = Exp({ mantissa: collateralFactorMantissa });\n\n // Get the normalized spot price of the asset\n vars.oraclePriceMantissa = ComptrollerInterface(comptrollerAddress).oracle().getUnderlyingPrice(\n address(vToken)\n );\n vars.oraclePrice = Exp({ mantissa: vars.oraclePriceMantissa });\n\n // Get bounded prices from DBO (used in CF-path liquidity calculations)\n IDeviationBoundedOracle boundedOracle = ComptrollerInterface(comptrollerAddress).deviationBoundedOracle();\n (uint256 boundedCollateralPriceMantissa, uint256 boundedDebtPriceMantissa) = boundedOracle.getBoundedPricesView(\n address(vToken)\n );\n\n // Collateral uses bounded collateral price (mirrors ComptrollerLens CF path)\n Exp memory collateralPrice = Exp({ mantissa: boundedCollateralPriceMantissa });\n vars.tokensToDenom = mul_(mul_(vars.collateralFactor, vars.exchangeRate), collateralPrice);\n vars.collateral = mul_ScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\n\n // Supply in USD uses spot price (real market value of supplied assets)\n vars.balanceOfUnderlying = vToken.balanceOfUnderlying(account);\n vars.supplyInUsd = mul_ScalarTruncate(vars.oraclePrice, vars.balanceOfUnderlying);\n\n // Borrows in USD uses bounded debt price (mirrors ComptrollerLens CF path)\n Exp memory debtPrice = Exp({ mantissa: boundedDebtPriceMantissa });\n vars.borrowsInUsd = mul_ScalarTruncate(debtPrice, vars.borrowBalance);\n\n address underlyingAssetAddress;\n uint underlyingDecimals;\n\n if (compareStrings(vToken.symbol(), \"vBNB\")) {\n underlyingAssetAddress = address(0);\n underlyingDecimals = 18;\n } else {\n VBep20 vBep20 = VBep20(address(vToken));\n underlyingAssetAddress = vBep20.underlying();\n underlyingDecimals = IERC20Metadata(vBep20.underlying()).decimals();\n }\n\n vars.isACollateral = isACollateral(account, address(vToken), comptrollerAddress);\n\n return\n AccountSnapshot({\n account: account,\n assetName: vToken.name(),\n vTokenAddress: address(vToken),\n underlyingAssetAddress: underlyingAssetAddress,\n supply: vars.balanceOfUnderlying,\n supplyInUsd: vars.supplyInUsd,\n collateral: vars.collateral,\n borrows: vars.borrowBalance,\n borrowsInUsd: vars.borrowsInUsd,\n spotPrice: vars.oraclePriceMantissa,\n boundedCollateralPrice: boundedCollateralPriceMantissa,\n boundedDebtPrice: boundedDebtPriceMantissa,\n accruedInterest: vToken.borrowIndex(),\n vTokenDecimals: vToken.decimals(),\n underlyingDecimals: underlyingDecimals,\n exchangeRate: vToken.exchangeRateCurrent(),\n isACollateral: vars.isACollateral\n });\n }\n\n // utilities\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}\n" + }, + "contracts/lib/approveOrRevert.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\n\n/// @notice Thrown if a contract is unable to approve a transfer\nerror ApproveFailed();\n\n/// @notice Approves a transfer, ensuring that it is successful. This function supports non-compliant\n/// tokens like the ones that don't return a boolean value on success. Thus, such approve call supports\n/// three different kinds of tokens:\n/// * Compliant tokens that revert on failure\n/// * Compliant tokens that return false on failure\n/// * Non-compliant tokens that don't return a value\n/// @param token The contract address of the token which will be transferred\n/// @param spender The spender contract address\n/// @param amount The value of the transfer\nfunction approveOrRevert(IERC20Upgradeable token, address spender, uint256 amount) {\n bytes memory callData = abi.encodeCall(token.approve, (spender, amount));\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory result) = address(token).call(callData);\n\n if (!success || (result.length != 0 && !abi.decode(result, (bool)))) {\n revert ApproveFailed();\n }\n}\n" + }, + "contracts/lib/Currency.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n// This library is heavily inspired by Uniswap v4 Currency lib\n// (https://github.com/Uniswap/v4-core/blob/b230769238879e1d4f58ffa57a4696b0c390d188/src/types/Currency.sol)\n// Contrary to the implementation above, this library does not\n// use assembly to save gas. It rather relies on OpenZeppelin's\n// SafeERC20 to simplify the review and audits. This might change\n// in future if it's more heavily used by Venus contracts.\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\ntype Currency is address;\n\nlibrary CurrencyLibrary {\n using CurrencyLibrary for Currency;\n\n /// @notice Thrown when a native transfer fails\n error NativeTransferFailed();\n\n Currency public constant NATIVE = Currency.wrap(0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB);\n\n /**\n * @dev If currency is a token, invokes SafeERC20.forceApprove to allow spender\n * to spend the amount of tokens on behalf of the current contract. Otherwise,\n * does nothing.\n * @param currency Currency\n * @param spender The account approved to spend the tokens\n * @param amount The approved amount\n */\n function approve(Currency currency, address spender, uint256 amount) internal {\n if (!currency.isNative()) {\n // I'd rather use approveOrRevert instead of forceApprove\n // once we migrate to OZ v5: force-approve does approve(0)\n // before approving the amount, and it's not always\n // desirable. The users will need to pay gas unnecessarily,\n // and using just approve() is safe as long as we revert on\n // errors (approveOrRevert handles that) and reset the approvals\n // after transfers (which is a best practice recommended by\n // auditors anyway).\n SafeERC20.forceApprove(IERC20(Currency.unwrap(currency)), spender, amount);\n }\n }\n\n /**\n * @dev Transfers an amount of currency to the receiver. If currency is a token,\n * uses SafeERC20.safeTransfer, otherwise transfers the native currency using\n * the recommended approach (`receiver.call{value: amount}(\"\")`).\n * @param currency Currency\n * @param receiver The account that would receive the tokens\n * @param amount The amount to transfer\n */\n function transfer(Currency currency, address receiver, uint256 amount) internal {\n if (currency.isNative()) {\n (bool success, ) = receiver.call{ value: amount }(\"\");\n if (!success) {\n revert NativeTransferFailed();\n }\n } else {\n SafeERC20.safeTransfer(IERC20(Currency.unwrap(currency)), receiver, amount);\n }\n }\n\n function transferAll(Currency currency, address receiver) internal {\n uint256 balance = currency.balanceOfSelf();\n if (balance > 0) {\n currency.transfer(receiver, balance);\n }\n }\n\n function balanceOfSelf(Currency currency) internal view returns (uint256) {\n if (currency.isNative()) {\n return address(this).balance;\n }\n return IERC20(Currency.unwrap(currency)).balanceOf(address(this));\n }\n\n function isNative(Currency currency) internal pure returns (bool) {\n return Currency.unwrap(currency) == Currency.unwrap(NATIVE);\n }\n}\n" + }, + "contracts/Liquidator/BUSDLiquidator.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { MANTISSA_ONE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\n\nimport { approveOrRevert } from \"../lib/approveOrRevert.sol\";\nimport { ILiquidator, IComptroller, IVToken, IVBep20, IVBNB, IVAIController } from \"../InterfacesV8.sol\";\n\n/**\n * @title BUSDLiquidator\n * @author Venus\n * @notice A custom contract for force-liquidating BUSD debts\n */\ncontract BUSDLiquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n using SafeERC20Upgradeable for IVToken;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IVBep20 public immutable vBUSD;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IComptroller public immutable comptroller;\n\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable treasury;\n\n /// @notice The liquidator's share, scaled by 1e18 (e.g. 1.02 * 1e18 for 102% of the debt covered)\n uint256 public liquidatorShareMantissa;\n\n /// @notice Thrown if trying to set liquidator's share lower than 100% of the debt covered\n error LiquidatorShareTooLow(uint256 liquidatorShareMantissa_);\n\n /// @notice Thrown if trying to set liquidator's share larger than this contract can receive from a liquidation\n error LiquidatorShareTooHigh(uint256 maxLiquidatorShareMantissa, uint256 liquidatorShareMantissa_);\n\n /// @notice Emitted when the liquidator's share is set\n event NewLiquidatorShare(uint256 oldLiquidatorShareMantissa, uint256 newLiquidatorShareMantissa);\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @param comptroller_ The address of the Comptroller contract\n /// @param vBUSD_ The address of the VBNB\n /// @param treasury_ The address of Venus treasury\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address comptroller_, address vBUSD_, address treasury_) {\n ensureNonzeroAddress(vBUSD_);\n ensureNonzeroAddress(comptroller_);\n ensureNonzeroAddress(treasury_);\n vBUSD = IVBep20(vBUSD_);\n comptroller = IComptroller(comptroller_);\n treasury = treasury_;\n _disableInitializers();\n }\n\n /// @notice Initializer for the implementation contract.\n /// @param liquidatorShareMantissa_ Liquidator's share, scaled by 1e18 (e.g. 1.01 * 1e18 for 101%)\n /// @custom:error LiquidatorShareTooHigh is thrown if trying to set liquidator percent larger than the liquidation profit\n function initialize(uint256 liquidatorShareMantissa_) external virtual initializer {\n __Ownable2Step_init();\n __ReentrancyGuard_init();\n _validateLiquidatorShareMantissa(liquidatorShareMantissa_);\n liquidatorShareMantissa = liquidatorShareMantissa_;\n }\n\n /// @notice Liquidate the entire BUSD debt of a borrower, seizing vTokenCollateral\n /// @param borrower The borrower whose debt should be liquidated\n /// @param vTokenCollateral The collateral to seize from the borrower\n function liquidateEntireBorrow(address borrower, IVToken vTokenCollateral) external nonReentrant {\n uint256 repayAmount = vBUSD.borrowBalanceCurrent(borrower);\n _unpauseAndLiquidate(borrower, repayAmount, vTokenCollateral);\n }\n\n /// @notice Liquidate a BUSD borrow, repaying the repayAmount of BUSD\n /// @param borrower The borrower whose debt should be liquidated\n /// @param repayAmount The amount to repay\n /// @param vTokenCollateral The collateral to seize from the borrower\n function liquidateBorrow(address borrower, uint256 repayAmount, IVToken vTokenCollateral) external nonReentrant {\n _unpauseAndLiquidate(borrower, repayAmount, vTokenCollateral);\n }\n\n /// @notice Allows Governance to set the liquidator's share\n /// @param liquidatorShareMantissa_ Liquidator's share, scaled by 1e18 (e.g. 1.01 * 1e18 for 101%)\n /// @custom:access Only Governance\n function setLiquidatorShare(uint256 liquidatorShareMantissa_) external onlyOwner {\n _validateLiquidatorShareMantissa(liquidatorShareMantissa_);\n uint256 oldLiquidatorShareMantissa = liquidatorShareMantissa;\n liquidatorShareMantissa = liquidatorShareMantissa_;\n emit NewLiquidatorShare(oldLiquidatorShareMantissa, liquidatorShareMantissa_);\n }\n\n /// @notice Allows to recover token accidentally sent to this contract by sending the entire balance to Governance\n /// @param token The address of the token to recover\n /// @custom:access Only Governance\n function sweepToken(IERC20Upgradeable token) external onlyOwner {\n token.safeTransfer(msg.sender, token.balanceOf(address(this)));\n }\n\n /// @dev Unpauses the liquidation on the BUSD market, liquidates the borrower's debt,\n /// and pauses the liquidations back\n /// @param borrower The borrower whose debt should be liquidated\n /// @param repayAmount The amount to repay\n /// @param vTokenCollateral The collateral to seize from the borrower\n function _unpauseAndLiquidate(address borrower, uint256 repayAmount, IVToken vTokenCollateral) internal {\n address[] memory vTokens = new address[](1);\n vTokens[0] = address(vBUSD);\n IComptroller.Action[] memory actions = new IComptroller.Action[](1);\n actions[0] = IComptroller.Action.LIQUIDATE;\n\n comptroller._setActionsPaused(vTokens, actions, false);\n _liquidateBorrow(borrower, repayAmount, vTokenCollateral);\n comptroller._setActionsPaused(vTokens, actions, true);\n }\n\n /// @dev Performs the actual liquidation, transferring BUSD from the sender to this contract,\n /// repaying the debt, and transferring the seized collateral to the sender and the treasury\n /// @param borrower The borrower whose debt should be liquidated\n /// @param repayAmount The amount to repay\n /// @param vTokenCollateral The collateral to seize from the borrower\n function _liquidateBorrow(address borrower, uint256 repayAmount, IVToken vTokenCollateral) internal {\n ILiquidator liquidatorContract = ILiquidator(comptroller.liquidatorContract());\n IERC20Upgradeable busd = IERC20Upgradeable(vBUSD.underlying());\n\n uint256 actualRepayAmount = _transferIn(busd, msg.sender, repayAmount);\n approveOrRevert(busd, address(liquidatorContract), actualRepayAmount);\n uint256 balanceBefore = vTokenCollateral.balanceOf(address(this));\n liquidatorContract.liquidateBorrow(address(vBUSD), borrower, actualRepayAmount, vTokenCollateral);\n uint256 receivedAmount = vTokenCollateral.balanceOf(address(this)) - balanceBefore;\n approveOrRevert(busd, address(liquidatorContract), 0);\n (uint256 liquidatorAmount, uint256 treasuryAmount) = _computeShares(\n receivedAmount,\n borrower,\n address(vTokenCollateral)\n );\n vTokenCollateral.safeTransfer(msg.sender, liquidatorAmount);\n vTokenCollateral.safeTransfer(treasury, treasuryAmount);\n }\n\n /// @dev Transfers tokens to this contract and returns the actual transfer amount\n /// @param token The token to transfer\n /// @param from The account to transfer from\n /// @param amount The amount to transfer\n /// @return The actual amount transferred\n function _transferIn(IERC20Upgradeable token, address from, uint256 amount) internal returns (uint256) {\n uint256 prevBalance = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n return token.balanceOf(address(this)) - prevBalance;\n }\n\n /// @notice Computes the liquidator's and treasury's shares from the received liquidation amount\n /// @param receivedAmount The total amount received from liquidating the borrower's collateral\n /// @param borrower The account whose collateral was liquidated\n /// @param vTokenCollateral The vToken representing the collateral asset\n /// @return liquidatorAmount The portion of `receivedAmount` allocated to the liquidator\n /// @return treasuryAmount The portion of `receivedAmount` allocated to the treasury\n function _computeShares(\n uint256 receivedAmount,\n address borrower,\n address vTokenCollateral\n ) internal view returns (uint256 liquidatorAmount, uint256 treasuryAmount) {\n uint256 effectiveIncentive = _getEffectiveIncentive(borrower, vTokenCollateral);\n\n // The bonus portion only (extra incentive above 100%)\n uint256 bonusAmount = (receivedAmount * (effectiveIncentive - MANTISSA_ONE)) / effectiveIncentive;\n\n // Treasury takes a fixed % of the bonus\n uint256 treasuryPercentMantissa = MANTISSA_ONE - liquidatorShareMantissa;\n treasuryAmount = (bonusAmount * treasuryPercentMantissa) / MANTISSA_ONE;\n\n // Liquidator gets the rest\n liquidatorAmount = receivedAmount - treasuryAmount;\n }\n\n /// @notice Computes the effective liquidation incentive after accounting the Liquidatior Contract treasury share\n /// @param borrower The account whose collateral is being evaluated\n /// @param vTokenCollateral The vToken representing the collateral asset\n /// @return effectiveIncentiveMantissa The incentive after accounting the Liquidatior Contract treasury share\n function _getEffectiveIncentive(address borrower, address vTokenCollateral) internal view returns (uint256) {\n uint256 totalIncentive = comptroller.getEffectiveLiquidationIncentive(borrower, vTokenCollateral);\n uint256 treasuryPercent = ILiquidator(comptroller.liquidatorContract()).treasuryPercentMantissa();\n\n // Bonus portion after subtracting treasury share\n uint256 adjustedBonus = ((totalIncentive - MANTISSA_ONE) * (MANTISSA_ONE - treasuryPercent)) / MANTISSA_ONE;\n\n // Return effective incentive\n return MANTISSA_ONE + adjustedBonus;\n }\n\n /// @notice Validates that the liquidator's share of the bonus is within acceptable bounds\n /// @dev `liquidatorShareMantissa_` represents the percentage of the bonus portion (extra above 100%).\n /// For example, if the liquidation incentive is 1.1 (i.e., 10% bonus), `liquidatorShareMantissa_`\n /// of 0.5e18 means the liquidator gets 50% of that 10% bonus.\n /// Must not exceed 100% (1e18) of the bonus.\n /// @param liquidatorShareMantissa_ The liquidator's share of the bonus, scaled by 1e18\n function _validateLiquidatorShareMantissa(uint256 liquidatorShareMantissa_) internal view {\n if (liquidatorShareMantissa_ > MANTISSA_ONE) {\n revert LiquidatorShareTooHigh(MANTISSA_ONE, liquidatorShareMantissa_);\n }\n }\n}\n" + }, + "contracts/Liquidator/Liquidator.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { Ownable2StepUpgradeable } from \"@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol\";\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport { SafeERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { IProtocolShareReserve } from \"../external/IProtocolShareReserve.sol\";\nimport { IWBNB } from \"../external/IWBNB.sol\";\nimport { LiquidatorStorage } from \"./LiquidatorStorage.sol\";\nimport { IComptroller, IVToken, IVBep20, IVBNB, IVAIController } from \"../InterfacesV8.sol\";\n\ncontract Liquidator is Ownable2StepUpgradeable, ReentrancyGuardUpgradeable, LiquidatorStorage, AccessControlledV8 {\n /// @notice Address of vBNB contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IVBNB public immutable vBnb;\n\n /// @notice Address of Venus Unitroller contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IComptroller public immutable comptroller;\n\n /// @notice Address of VAIUnitroller contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IVAIController public immutable vaiController;\n\n /// @notice Address of wBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable wBNB;\n\n /// @dev A unit (literal one) in EXP_SCALE, usually used in additions/subtractions\n uint256 internal constant MANTISSA_ONE = 1e18;\n\n /* Events */\n\n /// @notice Emitted when the percent of the seized amount that goes to treasury changes.\n event NewLiquidationTreasuryPercent(uint256 oldPercent, uint256 newPercent);\n\n /// @notice Emitted when a borrow is liquidated\n event LiquidateBorrowedTokens(\n address indexed liquidator,\n address indexed borrower,\n uint256 repayAmount,\n address vTokenBorrowed,\n address indexed vTokenCollateral,\n uint256 seizeTokensForTreasury,\n uint256 seizeTokensForLiquidator\n );\n\n /// @notice Emitted when the liquidation is restricted for a borrower\n event LiquidationRestricted(address indexed borrower);\n\n /// @notice Emitted when the liquidation restrictions are removed for a borrower\n event LiquidationRestrictionsDisabled(address indexed borrower);\n\n /// @notice Emitted when a liquidator is added to the allowedLiquidatorsByAccount mapping\n event AllowlistEntryAdded(address indexed borrower, address indexed liquidator);\n\n /// @notice Emitted when a liquidator is removed from the allowedLiquidatorsByAccount mapping\n event AllowlistEntryRemoved(address indexed borrower, address indexed liquidator);\n\n /// @notice Emitted when the amount of minLiquidatableVAI is updated\n event NewMinLiquidatableVAI(uint256 oldMinLiquidatableVAI, uint256 newMinLiquidatableVAI);\n\n /// @notice Emitted when the length of chunk gets updated\n event NewPendingRedeemChunkLength(uint256 oldPendingRedeemChunkLength, uint256 newPendingRedeemChunkLength);\n\n /// @notice Emitted when force liquidation is paused\n event ForceVAILiquidationPaused(address indexed sender);\n\n /// @notice Emitted when force liquidation is resumed\n event ForceVAILiquidationResumed(address indexed sender);\n\n /// @notice Emitted when new address of protocol share reserve is set\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserves);\n\n /// @notice Emitted when reserves are reduced from liquidator contract to protocol share reserves\n event ProtocolLiquidationIncentiveTransferred(address indexed sender, address indexed token, uint256 reducedAmount);\n\n /* Errors */\n\n /// @notice Thrown if the liquidation is restricted and the liquidator is not in the allowedLiquidatorsByAccount mapping\n error LiquidationNotAllowed(address borrower, address liquidator);\n\n /// @notice Thrown if VToken transfer fails after the liquidation\n error VTokenTransferFailed(address from, address to, uint256 amount);\n\n /// @notice Thrown if the liquidation is not successful (the error code is from TokenErrorReporter)\n error LiquidationFailed(uint256 errorCode);\n\n /// @notice Thrown if trying to restrict liquidations for an already restricted borrower\n error AlreadyRestricted(address borrower);\n\n /// @notice Thrown if trying to unrestrict liquidations for a borrower that is not restricted\n error NoRestrictionsExist(address borrower);\n\n /// @notice Thrown if the liquidator is already in the allowedLiquidatorsByAccount mapping\n error AlreadyAllowed(address borrower, address liquidator);\n\n /// @notice Thrown if trying to remove a liquidator that is not in the allowedLiquidatorsByAccount mapping\n error AllowlistEntryNotFound(address borrower, address liquidator);\n\n /// @notice Thrown if BNB amount sent with the transaction doesn't correspond to the\n /// intended BNB repayment\n error WrongTransactionAmount(uint256 expected, uint256 actual);\n\n /// @notice Thrown if trying to set treasury percent larger than the liquidation profit\n error TreasuryPercentTooHigh(uint256 maxTreasuryPercentMantissa, uint256 treasuryPercentMantissa_);\n\n /// @notice Thrown if trying to liquidate any token when VAI debt is too high\n error VAIDebtTooHigh(uint256 vaiDebt, uint256 minLiquidatableVAI);\n\n /// @notice Thrown when vToken is not listed\n error MarketNotListed(address vToken);\n\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @param comptroller_ The address of the Comptroller contract\n /// @param vBnb_ The address of the VBNB\n /// @param wBNB_ The address of wBNB\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address comptroller_, address payable vBnb_, address wBNB_) {\n ensureNonzeroAddress(vBnb_);\n ensureNonzeroAddress(comptroller_);\n ensureNonzeroAddress(wBNB_);\n vBnb = IVBNB(vBnb_);\n wBNB = wBNB_;\n comptroller = IComptroller(comptroller_);\n vaiController = IVAIController(IComptroller(comptroller_).vaiController());\n _disableInitializers();\n }\n\n receive() external payable {}\n\n /// @notice Initializer for the implementation contract.\n /// @param treasuryPercentMantissa_ Treasury share, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)\n /// @param accessControlManager_ address of access control manager\n /// @param protocolShareReserve_ The address of the protocol share reserve contract\n function initialize(\n uint256 treasuryPercentMantissa_,\n address accessControlManager_,\n address protocolShareReserve_\n ) external virtual reinitializer(2) {\n __Liquidator_init(treasuryPercentMantissa_, accessControlManager_, protocolShareReserve_);\n }\n\n /// @dev Liquidator initializer for derived contracts.\n /// @param treasuryPercentMantissa_ Treasury share, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)\n /// @param accessControlManager_ address of access control manager\n /// @param protocolShareReserve_ The address of the protocol share reserve contract\n function __Liquidator_init(\n uint256 treasuryPercentMantissa_,\n address accessControlManager_,\n address protocolShareReserve_\n ) internal onlyInitializing {\n __Ownable2Step_init();\n __ReentrancyGuard_init();\n __Liquidator_init_unchained(treasuryPercentMantissa_, protocolShareReserve_);\n __AccessControlled_init_unchained(accessControlManager_);\n }\n\n /// @dev Liquidator initializer for derived contracts that doesn't call parent initializers.\n /// @param treasuryPercentMantissa_ Treasury share, scaled by 1e18 (e.g. 0.2 * 1e18 for 20%)\n /// @param protocolShareReserve_ The address of the protocol share reserve contract\n function __Liquidator_init_unchained(\n uint256 treasuryPercentMantissa_,\n address protocolShareReserve_\n ) internal onlyInitializing {\n validateTreasuryPercentMantissa(treasuryPercentMantissa_);\n treasuryPercentMantissa = treasuryPercentMantissa_;\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /// @notice An admin function to restrict liquidations to allowed addresses only.\n /// @dev Use {addTo,removeFrom}AllowList to configure the allowed addresses.\n /// @param borrower The address of the borrower\n function restrictLiquidation(address borrower) external {\n _checkAccessAllowed(\"restrictLiquidation(address)\");\n if (liquidationRestricted[borrower]) {\n revert AlreadyRestricted(borrower);\n }\n liquidationRestricted[borrower] = true;\n emit LiquidationRestricted(borrower);\n }\n\n /// @notice An admin function to remove restrictions for liquidations.\n /// @dev Does not impact the allowedLiquidatorsByAccount mapping for the borrower, just turns off the check.\n /// @param borrower The address of the borrower\n function unrestrictLiquidation(address borrower) external {\n _checkAccessAllowed(\"unrestrictLiquidation(address)\");\n if (!liquidationRestricted[borrower]) {\n revert NoRestrictionsExist(borrower);\n }\n liquidationRestricted[borrower] = false;\n emit LiquidationRestrictionsDisabled(borrower);\n }\n\n /// @notice An admin function to add the liquidator to the allowedLiquidatorsByAccount mapping for a certain\n /// borrower. If the liquidations are restricted, only liquidators from the\n /// allowedLiquidatorsByAccount mapping can participate in liquidating the positions of this borrower.\n /// @param borrower The address of the borrower\n /// @param borrower The address of the liquidator\n function addToAllowlist(address borrower, address liquidator) external {\n _checkAccessAllowed(\"addToAllowlist(address,address)\");\n if (allowedLiquidatorsByAccount[borrower][liquidator]) {\n revert AlreadyAllowed(borrower, liquidator);\n }\n allowedLiquidatorsByAccount[borrower][liquidator] = true;\n emit AllowlistEntryAdded(borrower, liquidator);\n }\n\n /// @notice An admin function to remove the liquidator from the allowedLiquidatorsByAccount mapping of a certain\n /// borrower. If the liquidations are restricted, this liquidator will not be\n /// able to liquidate the positions of this borrower.\n /// @param borrower The address of the borrower\n /// @param borrower The address of the liquidator\n function removeFromAllowlist(address borrower, address liquidator) external {\n _checkAccessAllowed(\"removeFromAllowlist(address,address)\");\n if (!allowedLiquidatorsByAccount[borrower][liquidator]) {\n revert AllowlistEntryNotFound(borrower, liquidator);\n }\n allowedLiquidatorsByAccount[borrower][liquidator] = false;\n emit AllowlistEntryRemoved(borrower, liquidator);\n }\n\n /// @notice Liquidates a borrow and splits the seized amount between protocol share reserve and\n /// liquidator. The liquidators should use this interface instead of calling\n /// vToken.liquidateBorrow(...) directly.\n /// @notice Checks force VAI liquidation first; vToken should be address of vaiController if vaiDebt is greater than threshold\n /// @notice For BNB borrows msg.value should be equal to repayAmount; otherwise msg.value\n /// should be zero.\n /// @param vToken Borrowed vToken\n /// @param borrower The address of the borrower\n /// @param repayAmount The amount to repay on behalf of the borrower\n /// @param vTokenCollateral The collateral to seize\n function liquidateBorrow(\n address vToken,\n address borrower,\n uint256 repayAmount,\n IVToken vTokenCollateral\n ) external payable nonReentrant {\n ensureNonzeroAddress(borrower);\n checkRestrictions(borrower, msg.sender);\n (bool isListed, , ) = IComptroller(comptroller).markets(address(vTokenCollateral));\n if (!isListed) {\n revert MarketNotListed(address(vTokenCollateral));\n }\n\n _checkForceVAILiquidate(vToken, borrower);\n uint256 ourBalanceBefore = vTokenCollateral.balanceOf(address(this));\n if (vToken == address(vBnb)) {\n if (repayAmount != msg.value) {\n revert WrongTransactionAmount(repayAmount, msg.value);\n }\n vBnb.liquidateBorrow{ value: msg.value }(borrower, vTokenCollateral);\n } else {\n if (msg.value != 0) {\n revert WrongTransactionAmount(0, msg.value);\n }\n if (vToken == address(vaiController)) {\n _liquidateVAI(borrower, repayAmount, vTokenCollateral);\n } else {\n _liquidateBep20(IVBep20(vToken), borrower, repayAmount, vTokenCollateral);\n }\n }\n uint256 ourBalanceAfter = vTokenCollateral.balanceOf(address(this));\n uint256 seizedAmount = ourBalanceAfter - ourBalanceBefore;\n (uint256 ours, uint256 theirs) = _distributeLiquidationIncentive(borrower, vTokenCollateral, seizedAmount);\n _reduceReservesInternal();\n emit LiquidateBorrowedTokens(\n msg.sender,\n borrower,\n repayAmount,\n vToken,\n address(vTokenCollateral),\n ours,\n theirs\n );\n }\n\n /// @notice Sets the new percent of the seized amount that goes to treasury. Should\n /// be less than or equal to comptroller.liquidationIncentiveMantissa().sub(1e18).\n /// @param newTreasuryPercentMantissa New treasury percent (scaled by 10^18).\n function setTreasuryPercent(uint256 newTreasuryPercentMantissa) external {\n _checkAccessAllowed(\"setTreasuryPercent(uint256)\");\n validateTreasuryPercentMantissa(newTreasuryPercentMantissa);\n emit NewLiquidationTreasuryPercent(treasuryPercentMantissa, newTreasuryPercentMantissa);\n treasuryPercentMantissa = newTreasuryPercentMantissa;\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protocolShareReserve_ The address of the protocol share reserve contract\n */\n function setProtocolShareReserve(address payable protocolShareReserve_) external onlyOwner {\n _setProtocolShareReserve(protocolShareReserve_);\n }\n\n /**\n * @notice Reduce the reserves of the pending accumulated reserves\n */\n function reduceReserves() external nonReentrant {\n _reduceReservesInternal();\n }\n\n function _reduceReservesInternal() internal {\n uint256 _pendingRedeemLength = pendingRedeem.length;\n uint256 range = _pendingRedeemLength >= pendingRedeemChunkLength\n ? pendingRedeemChunkLength\n : _pendingRedeemLength;\n for (uint256 index = range; index > 0; ) {\n address vToken = pendingRedeem[index - 1];\n uint256 vTokenBalance_ = IVToken(vToken).balanceOf(address(this));\n if (_redeemUnderlying(vToken, vTokenBalance_)) {\n if (vToken == address(vBnb)) {\n _reduceBnbReserves();\n } else {\n _reduceVTokenReserves(vToken);\n }\n pendingRedeem[index - 1] = pendingRedeem[pendingRedeem.length - 1];\n pendingRedeem.pop();\n }\n unchecked {\n index--;\n }\n }\n }\n\n /// @dev Transfers BEP20 tokens to self, then approves vToken to take these tokens.\n function _liquidateBep20(IVBep20 vToken, address borrower, uint256 repayAmount, IVToken vTokenCollateral) internal {\n (bool isListed, , ) = IComptroller(comptroller).markets(address(vToken));\n if (!isListed) {\n revert MarketNotListed(address(vToken));\n }\n\n IERC20Upgradeable borrowedToken = IERC20Upgradeable(vToken.underlying());\n uint256 actualRepayAmount = _transferBep20(borrowedToken, msg.sender, address(this), repayAmount);\n borrowedToken.safeApprove(address(vToken), 0);\n borrowedToken.safeApprove(address(vToken), actualRepayAmount);\n requireNoError(vToken.liquidateBorrow(borrower, actualRepayAmount, vTokenCollateral));\n }\n\n /// @dev Transfers BEP20 tokens to self, then approves VAI to take these tokens.\n function _liquidateVAI(address borrower, uint256 repayAmount, IVToken vTokenCollateral) internal {\n IERC20Upgradeable vai = IERC20Upgradeable(vaiController.getVAIAddress());\n vai.safeTransferFrom(msg.sender, address(this), repayAmount);\n vai.safeApprove(address(vaiController), 0);\n vai.safeApprove(address(vaiController), repayAmount);\n\n (uint256 err, ) = vaiController.liquidateVAI(borrower, repayAmount, vTokenCollateral);\n requireNoError(err);\n }\n\n /// @dev Distribute seized collateral between liquidator and protocol share reserve\n function _distributeLiquidationIncentive(\n address borrower,\n IVToken vTokenCollateral,\n uint256 seizedAmount\n ) internal returns (uint256 ours, uint256 theirs) {\n (ours, theirs) = _splitLiquidationIncentive(borrower, address(vTokenCollateral), seizedAmount);\n if (!vTokenCollateral.transfer(msg.sender, theirs)) {\n revert VTokenTransferFailed(address(this), msg.sender, theirs);\n }\n\n if (ours > 0 && !_redeemUnderlying(address(vTokenCollateral), ours)) {\n // Check if asset is already present in pendingRedeem array\n uint256 index;\n for (index; index < pendingRedeem.length; ) {\n if (pendingRedeem[index] == address(vTokenCollateral)) {\n break;\n }\n unchecked {\n index++;\n }\n }\n if (index == pendingRedeem.length) {\n pendingRedeem.push(address(vTokenCollateral));\n }\n } else {\n if (address(vTokenCollateral) == address(vBnb)) {\n _reduceBnbReserves();\n } else {\n _reduceVTokenReserves(address(vTokenCollateral));\n }\n }\n }\n\n /// @dev Wraps BNB to wBNB and sends to protocol share reserve\n function _reduceBnbReserves() private {\n uint256 bnbBalance = address(this).balance;\n IWBNB(wBNB).deposit{ value: bnbBalance }();\n IERC20Upgradeable(wBNB).safeTransfer(protocolShareReserve, bnbBalance);\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n wBNB,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n emit ProtocolLiquidationIncentiveTransferred(msg.sender, wBNB, bnbBalance);\n }\n\n /// @dev Redeem seized collateral to underlying assets\n function _redeemUnderlying(address vToken, uint256 amount) private returns (bool) {\n try IVToken(address(vToken)).redeem(amount) returns (uint256 response) {\n if (response == 0) {\n return true;\n } else {\n return false;\n }\n } catch {\n return false;\n }\n }\n\n /// @dev Transfers seized collateral other than BNB to protocol share reserve\n function _reduceVTokenReserves(address vToken) private {\n address underlying = IVBep20(vToken).underlying();\n uint256 underlyingBalance = IERC20Upgradeable(underlying).balanceOf(address(this));\n IERC20Upgradeable(underlying).safeTransfer(protocolShareReserve, underlyingBalance);\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.LIQUIDATION\n );\n emit ProtocolLiquidationIncentiveTransferred(msg.sender, underlying, underlyingBalance);\n }\n\n /// @dev Transfers tokens and returns the actual transfer amount\n function _transferBep20(\n IERC20Upgradeable token,\n address from,\n address to,\n uint256 amount\n ) internal returns (uint256) {\n uint256 prevBalance = token.balanceOf(to);\n token.safeTransferFrom(from, to, amount);\n return token.balanceOf(to) - prevBalance;\n }\n\n /// @dev Computes the amounts that would go to treasury and to the liquidator.\n function _splitLiquidationIncentive(\n address borrower,\n address vTokenCollateral,\n uint256 seizedAmount\n ) internal view returns (uint256 ours, uint256 theirs) {\n uint256 totalIncentive = comptroller.getEffectiveLiquidationIncentive(borrower, vTokenCollateral);\n uint256 bonusMantissa = totalIncentive - MANTISSA_ONE;\n\n // Our share is % of bonus portion only\n uint256 bonusAmount = (seizedAmount * bonusMantissa) / totalIncentive;\n ours = (bonusAmount * treasuryPercentMantissa) / MANTISSA_ONE;\n\n theirs = seizedAmount - ours;\n }\n\n function requireNoError(uint256 errCode) internal pure {\n if (errCode == uint256(0)) {\n return;\n }\n\n revert LiquidationFailed(errCode);\n }\n\n function checkRestrictions(address borrower, address liquidator) internal view {\n if (liquidationRestricted[borrower] && !allowedLiquidatorsByAccount[borrower][liquidator]) {\n revert LiquidationNotAllowed(borrower, liquidator);\n }\n }\n\n function validateTreasuryPercentMantissa(uint256 treasuryPercentMantissa_) internal view {\n if (treasuryPercentMantissa_ > MANTISSA_ONE) {\n revert TreasuryPercentTooHigh(MANTISSA_ONE, treasuryPercentMantissa_);\n }\n }\n\n /// @dev Checks liquidation action in comptroller and vaiDebt with minLiquidatableVAI threshold\n function _checkForceVAILiquidate(address vToken_, address borrower_) private view {\n uint256 _vaiDebt = vaiController.getVAIRepayAmount(borrower_);\n bool _isVAILiquidationPaused = comptroller.actionPaused(address(vaiController), IComptroller.Action.LIQUIDATE);\n bool _isForcedLiquidationEnabled = comptroller.isForcedLiquidationEnabled(vToken_);\n if (\n _isForcedLiquidationEnabled ||\n _isVAILiquidationPaused ||\n !forceVAILiquidate ||\n _vaiDebt < minLiquidatableVAI ||\n vToken_ == address(vaiController)\n ) return;\n revert VAIDebtTooHigh(_vaiDebt, minLiquidatableVAI);\n }\n\n function _setProtocolShareReserve(address protocolShareReserve_) internal {\n ensureNonzeroAddress(protocolShareReserve_);\n emit NewProtocolShareReserve(protocolShareReserve, protocolShareReserve_);\n protocolShareReserve = protocolShareReserve_;\n }\n\n /**\n * @notice Sets the threshold for minimum amount of vaiLiquidate\n * @param minLiquidatableVAI_ New address for the access control\n */\n function setMinLiquidatableVAI(uint256 minLiquidatableVAI_) external {\n _checkAccessAllowed(\"setMinLiquidatableVAI(uint256)\");\n emit NewMinLiquidatableVAI(minLiquidatableVAI, minLiquidatableVAI_);\n minLiquidatableVAI = minLiquidatableVAI_;\n }\n\n /**\n * @notice Length of the pendingRedeem array to be consider while redeeming in Liquidation transaction\n * @param newLength_ Length of the chunk\n */\n function setPendingRedeemChunkLength(uint256 newLength_) external {\n _checkAccessAllowed(\"setPendingRedeemChunkLength(uint256)\");\n require(newLength_ > 0, \"Invalid chunk size\");\n emit NewPendingRedeemChunkLength(pendingRedeemChunkLength, newLength_);\n pendingRedeemChunkLength = newLength_;\n }\n\n /**\n * @notice Pause Force Liquidation of VAI\n */\n function pauseForceVAILiquidate() external {\n _checkAccessAllowed(\"pauseForceVAILiquidate()\");\n require(forceVAILiquidate, \"Force Liquidation of VAI is already Paused\");\n forceVAILiquidate = false;\n emit ForceVAILiquidationPaused(msg.sender);\n }\n\n /**\n * @notice Resume Force Liquidation of VAI\n */\n function resumeForceVAILiquidate() external {\n _checkAccessAllowed(\"resumeForceVAILiquidate()\");\n require(!forceVAILiquidate, \"Force Liquidation of VAI is already resumed\");\n forceVAILiquidate = true;\n emit ForceVAILiquidationResumed(msg.sender);\n }\n\n function renounceOwnership() public override {}\n}\n" + }, + "contracts/Liquidator/LiquidatorStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ncontract LiquidatorStorage {\n /* State */\n\n /// @notice Percent of seized amount that goes to treasury.\n uint256 public treasuryPercentMantissa;\n\n /// @notice Mapping of addresses allowed to liquidate an account if liquidationRestricted[borrower] == true\n mapping(address => mapping(address => bool)) public allowedLiquidatorsByAccount;\n\n /// @notice Whether the liquidations are restricted to enabled allowedLiquidatorsByAccount addresses only\n mapping(address => bool) public liquidationRestricted;\n\n /// @notice minimum amount of VAI liquidation threshold\n uint256 public minLiquidatableVAI;\n\n /// @notice check for liquidation of VAI\n bool public forceVAILiquidate;\n\n /// @notice assests whose redeem is pending to reduce reserves\n address[] public pendingRedeem;\n\n /// @notice protocol share reserve contract address\n address public protocolShareReserve;\n\n /// @dev Size of chunk to consider when redeeming underlying at the time of liquidation\n uint256 internal pendingRedeemChunkLength;\n\n /// @notice gap to prevent collision in inheritance\n uint256[49] private __gap;\n}\n" + }, + "contracts/PegStability/IVAI.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IVAI {\n function balanceOf(address usr) external returns (uint256);\n\n function transferFrom(address src, address dst, uint amount) external returns (bool);\n\n function mint(address usr, uint wad) external;\n\n function burn(address usr, uint wad) external;\n}\n" + }, + "contracts/PegStability/PegStability.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\nimport \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IVAI } from \"./IVAI.sol\";\n\n/**\n * @title Peg Stability Contract.\n * @notice Contract for swapping stable token for VAI token and vice versa to maintain the peg stability between them.\n * @author Venus Protocol\n */\ncontract PegStability is AccessControlledV8, ReentrancyGuardUpgradeable {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n // Helper enum for calculation of the fee.\n enum FeeDirection {\n IN,\n OUT\n }\n\n /// @notice The divisor used to convert fees to basis points.\n uint256 public constant BASIS_POINTS_DIVISOR = 10000;\n\n /// @notice The mantissa value representing 1 (used for calculations).\n uint256 public constant MANTISSA_ONE = 1e18;\n\n /// @notice The value representing one dollar in the stable token.\n /// @dev Our oracle is returning amount depending on the number of decimals of the stable token. (36 - asset_decimals) E.g. 8 decimal asset = 1e28.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable ONE_DOLLAR;\n\n /// @notice VAI token contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n IVAI public immutable VAI;\n\n /// @notice The address of the stable token contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable STABLE_TOKEN_ADDRESS;\n\n /// @notice The address of ResilientOracle contract wrapped in its interface.\n ResilientOracleInterface public oracle;\n\n /// @notice The address of the Venus Treasury contract.\n address public venusTreasury;\n\n /// @notice The incoming stableCoin fee. (Fee for swapStableForVAI).\n uint256 public feeIn;\n\n /// @notice The outgoing stableCoin fee. (Fee for swapVAIForStable).\n uint256 public feeOut;\n\n /// @notice The maximum amount of VAI that can be minted through this contract.\n uint256 public vaiMintCap;\n\n /// @notice The total amount of VAI minted through this contract.\n uint256 public vaiMinted;\n\n /// @notice A flag indicating whether the contract is currently paused or not.\n bool public isPaused;\n\n /// @notice Event emitted when contract is paused.\n event PSMPaused(address indexed admin);\n\n /// @notice Event emitted when the contract is resumed after pause.\n event PSMResumed(address indexed admin);\n\n /// @notice Event emitted when feeIn state var is modified.\n event FeeInChanged(uint256 oldFeeIn, uint256 newFeeIn);\n\n /// @notice Event emitted when feeOut state var is modified.\n event FeeOutChanged(uint256 oldFeeOut, uint256 newFeeOut);\n\n /// @notice Event emitted when vaiMintCap state var is modified.\n event VAIMintCapChanged(uint256 oldCap, uint256 newCap);\n\n /// @notice Event emitted when venusTreasury state var is modified.\n event VenusTreasuryChanged(address indexed oldTreasury, address indexed newTreasury);\n\n /// @notice Event emitted when oracle state var is modified.\n event OracleChanged(address indexed oldOracle, address indexed newOracle);\n\n /// @notice Event emitted when stable token is swapped for VAI.\n event StableForVAISwapped(uint256 stableIn, uint256 vaiOut, uint256 fee);\n\n /// @notice Event emitted when stable token is swapped for VAI.\n event VAIForStableSwapped(uint256 vaiBurnt, uint256 stableOut, uint256 vaiFee);\n\n /// @notice thrown when contract is in paused state\n error Paused();\n\n /// @notice thrown when attempted to pause an already paused contract\n error AlreadyPaused();\n\n /// @notice thrown when attempted to resume the contract if it is already resumed\n error NotPaused();\n\n /// @notice thrown when stable token has more than 18 decimals\n error TooManyDecimals();\n\n /// @notice thrown when fee is >= 100%\n error InvalidFee();\n\n /// @notice thrown when a zero address is passed as a function parameter\n error ZeroAddress();\n\n /// @notice thrown when a zero amount is passed as stable token amount parameter\n error ZeroAmount();\n\n /// @notice thrown when the user doesn't have enough VAI balance to provide for the amount of stable tokens he wishes to get\n error NotEnoughVAI();\n\n /// @notice thrown when the amount of VAI to be burnt exceeds the vaiMinted amount\n error VAIMintedUnderflow();\n\n /// @notice thrown when the VAI transfer to treasury fails\n error VAITransferFail();\n\n /// @notice thrown when VAI to be minted will go beyond the mintCap threshold\n error VAIMintCapReached();\n /// @notice thrown when fee calculation will result in rounding down to 0 due to stable token amount being a too small number\n error AmountTooSmall();\n\n /**\n * @dev Prevents functions to execute when contract is paused.\n */\n modifier isActive() {\n if (isPaused) revert Paused();\n _;\n }\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address stableTokenAddress_, address vaiAddress_) {\n _ensureNonzeroAddress(stableTokenAddress_);\n _ensureNonzeroAddress(vaiAddress_);\n\n uint256 decimals_ = IERC20MetadataUpgradeable(stableTokenAddress_).decimals();\n\n if (decimals_ > 18) {\n revert TooManyDecimals();\n }\n\n ONE_DOLLAR = 10 ** (36 - decimals_); // 1$ scaled to the decimals returned by our Oracle\n STABLE_TOKEN_ADDRESS = stableTokenAddress_;\n VAI = IVAI(vaiAddress_);\n _disableInitializers();\n }\n\n /**\n * @notice Initializes the contract via Proxy Contract with the required parameters.\n * @param accessControlManager_ The address of the AccessControlManager contract.\n * @param venusTreasury_ The address where fees will be sent.\n * @param oracleAddress_ The address of the ResilientOracle contract.\n * @param feeIn_ The percentage of fees to be applied to a stablecoin -> VAI swap.\n * @param feeOut_ The percentage of fees to be applied to a VAI -> stablecoin swap.\n * @param vaiMintCap_ The cap for the total amount of VAI that can be minted.\n */\n function initialize(\n address accessControlManager_,\n address venusTreasury_,\n address oracleAddress_,\n uint256 feeIn_,\n uint256 feeOut_,\n uint256 vaiMintCap_\n ) external initializer {\n _ensureNonzeroAddress(accessControlManager_);\n _ensureNonzeroAddress(venusTreasury_);\n _ensureNonzeroAddress(oracleAddress_);\n __AccessControlled_init(accessControlManager_);\n __ReentrancyGuard_init();\n\n if (feeIn_ >= BASIS_POINTS_DIVISOR || feeOut_ >= BASIS_POINTS_DIVISOR) {\n revert InvalidFee();\n }\n\n feeIn = feeIn_;\n feeOut = feeOut_;\n vaiMintCap = vaiMintCap_;\n venusTreasury = venusTreasury_;\n oracle = ResilientOracleInterface(oracleAddress_);\n }\n\n /*** Swap Functions ***/\n\n /**\n * @notice Swaps VAI for a stable token.\n * @param receiver The address where the stablecoin will be sent.\n * @param stableTknAmount The amount of stable tokens to receive.\n * @return The amount of VAI received and burnt from the sender.\n */\n // @custom:event Emits VAIForStableSwapped event.\n function swapVAIForStable(\n address receiver,\n uint256 stableTknAmount\n ) external isActive nonReentrant returns (uint256) {\n _ensureNonzeroAddress(receiver);\n _ensureNonzeroAmount(stableTknAmount);\n\n // update oracle price and calculate USD value of the stable token amount scaled in 18 decimals\n oracle.updateAssetPrice(STABLE_TOKEN_ADDRESS);\n uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.OUT);\n uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.OUT);\n\n if (VAI.balanceOf(msg.sender) < stableTknAmountUSD + fee) {\n revert NotEnoughVAI();\n }\n if (vaiMinted < stableTknAmountUSD) {\n revert VAIMintedUnderflow();\n }\n\n unchecked {\n vaiMinted -= stableTknAmountUSD;\n }\n\n if (fee != 0) {\n bool success = VAI.transferFrom(msg.sender, venusTreasury, fee);\n if (!success) {\n revert VAITransferFail();\n }\n }\n\n VAI.burn(msg.sender, stableTknAmountUSD);\n IERC20Upgradeable(STABLE_TOKEN_ADDRESS).safeTransfer(receiver, stableTknAmount);\n emit VAIForStableSwapped(stableTknAmountUSD, stableTknAmount, fee);\n return stableTknAmountUSD;\n }\n\n /**\n * @notice Swaps stable tokens for VAI with fees.\n * @dev This function adds support to fee-on-transfer tokens. The actualTransferAmt is calculated, by recording token balance state before and after the transfer.\n * @param receiver The address that will receive the VAI tokens.\n * @param stableTknAmount The amount of stable tokens to be swapped.\n * @return Amount of VAI minted to the sender.\n */\n // @custom:event Emits StableForVAISwapped event.\n function swapStableForVAI(\n address receiver,\n uint256 stableTknAmount\n ) external isActive nonReentrant returns (uint256) {\n _ensureNonzeroAddress(receiver);\n _ensureNonzeroAmount(stableTknAmount);\n // transfer IN, supporting fee-on-transfer tokens\n uint256 balanceBefore = IERC20Upgradeable(STABLE_TOKEN_ADDRESS).balanceOf(address(this));\n IERC20Upgradeable(STABLE_TOKEN_ADDRESS).safeTransferFrom(msg.sender, address(this), stableTknAmount);\n uint256 balanceAfter = IERC20Upgradeable(STABLE_TOKEN_ADDRESS).balanceOf(address(this));\n\n //calculate actual transfered amount (in case of fee-on-transfer tokens)\n uint256 actualTransferAmt = balanceAfter - balanceBefore;\n\n // update oracle price and calculate USD value of the stable token amount scaled in 18 decimals\n oracle.updateAssetPrice(STABLE_TOKEN_ADDRESS);\n uint256 actualTransferAmtInUSD = _previewTokenUSDAmount(actualTransferAmt, FeeDirection.IN);\n\n //calculate feeIn\n uint256 fee = _calculateFee(actualTransferAmtInUSD, FeeDirection.IN);\n uint256 vaiToMint = actualTransferAmtInUSD - fee;\n\n if (vaiMinted + actualTransferAmtInUSD > vaiMintCap) {\n revert VAIMintCapReached();\n }\n unchecked {\n vaiMinted += actualTransferAmtInUSD;\n }\n\n // mint VAI to receiver\n VAI.mint(receiver, vaiToMint);\n\n // mint VAI fee to venus treasury\n if (fee != 0) {\n VAI.mint(venusTreasury, fee);\n }\n\n emit StableForVAISwapped(actualTransferAmt, vaiToMint, fee);\n return vaiToMint;\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Pause the PSM contract.\n * @dev Reverts if the contract is already paused.\n */\n // @custom:event Emits PSMPaused event.\n function pause() external {\n _checkAccessAllowed(\"pause()\");\n if (isPaused) {\n revert AlreadyPaused();\n }\n isPaused = true;\n emit PSMPaused(msg.sender);\n }\n\n /**\n * @notice Resume the PSM contract.\n * @dev Reverts if the contract is not paused.\n */\n // @custom:event Emits PSMResumed event.\n function resume() external {\n _checkAccessAllowed(\"resume()\");\n if (!isPaused) {\n revert NotPaused();\n }\n isPaused = false;\n emit PSMResumed(msg.sender);\n }\n\n /**\n * @notice Set the fee percentage for incoming swaps.\n * @dev Reverts if the new fee percentage is invalid (greater than or equal to BASIS_POINTS_DIVISOR).\n * @param feeIn_ The new fee percentage for incoming swaps.\n */\n // @custom:event Emits FeeInChanged event.\n function setFeeIn(uint256 feeIn_) external {\n _checkAccessAllowed(\"setFeeIn(uint256)\");\n // feeIn = 10000 = 100%\n if (feeIn_ >= BASIS_POINTS_DIVISOR) {\n revert InvalidFee();\n }\n uint256 oldFeeIn = feeIn;\n feeIn = feeIn_;\n emit FeeInChanged(oldFeeIn, feeIn_);\n }\n\n /**\n * @notice Set the fee percentage for outgoing swaps.\n * @dev Reverts if the new fee percentage is invalid (greater than or equal to BASIS_POINTS_DIVISOR).\n * @param feeOut_ The new fee percentage for outgoing swaps.\n */\n // @custom:event Emits FeeOutChanged event.\n function setFeeOut(uint256 feeOut_) external {\n _checkAccessAllowed(\"setFeeOut(uint256)\");\n // feeOut = 10000 = 100%\n if (feeOut_ >= BASIS_POINTS_DIVISOR) {\n revert InvalidFee();\n }\n uint256 oldFeeOut = feeOut;\n feeOut = feeOut_;\n emit FeeOutChanged(oldFeeOut, feeOut_);\n }\n\n /**\n * @dev Set the maximum amount of VAI that can be minted through this contract.\n * @param vaiMintCap_ The new maximum amount of VAI that can be minted.\n */\n // @custom:event Emits VAIMintCapChanged event.\n function setVAIMintCap(uint256 vaiMintCap_) external {\n _checkAccessAllowed(\"setVAIMintCap(uint256)\");\n uint256 oldVAIMintCap = vaiMintCap;\n vaiMintCap = vaiMintCap_;\n emit VAIMintCapChanged(oldVAIMintCap, vaiMintCap_);\n }\n\n /**\n * @notice Set the address of the Venus Treasury contract.\n * @dev Reverts if the new address is zero.\n * @param venusTreasury_ The new address of the Venus Treasury contract.\n */\n // @custom:event Emits VenusTreasuryChanged event.\n function setVenusTreasury(address venusTreasury_) external {\n _checkAccessAllowed(\"setVenusTreasury(address)\");\n _ensureNonzeroAddress(venusTreasury_);\n address oldTreasuryAddress = venusTreasury;\n venusTreasury = venusTreasury_;\n emit VenusTreasuryChanged(oldTreasuryAddress, venusTreasury_);\n }\n\n /**\n * @notice Set the address of the ResilientOracle contract.\n * @dev Reverts if the new address is zero.\n * @param oracleAddress_ The new address of the ResilientOracle contract.\n */\n // @custom:event Emits OracleChanged event.\n function setOracle(address oracleAddress_) external {\n _checkAccessAllowed(\"setOracle(address)\");\n _ensureNonzeroAddress(oracleAddress_);\n address oldOracleAddress = address(oracle);\n oracle = ResilientOracleInterface(oracleAddress_);\n emit OracleChanged(oldOracleAddress, oracleAddress_);\n }\n\n /**\n * @dev Disabling renounceOwnership function.\n */\n function renounceOwnership() public override {}\n\n /*** Helper Functions ***/\n\n /**\n * @notice Calculates the amount of VAI that would be burnt from the user.\n * @dev This calculation might be off with a bit, if the price of the oracle for this asset is not updated in the block this function is invoked.\n * @param stableTknAmount The amount of stable tokens to be received after the swap.\n * @return The amount of VAI that would be taken from the user.\n */\n function previewSwapVAIForStable(uint256 stableTknAmount) external view returns (uint256) {\n _ensureNonzeroAmount(stableTknAmount);\n uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.OUT);\n uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.OUT);\n\n if (vaiMinted < stableTknAmountUSD) {\n revert VAIMintedUnderflow();\n }\n\n return stableTknAmountUSD + fee;\n }\n\n /**\n * @notice Calculates the amount of VAI that would be sent to the receiver.\n * @dev This calculation might be off with a bit, if the price of the oracle for this asset is not updated in the block this function is invoked.\n * @param stableTknAmount The amount of stable tokens provided for the swap.\n * @return The amount of VAI that would be sent to the receiver.\n */\n function previewSwapStableForVAI(uint256 stableTknAmount) external view returns (uint256) {\n _ensureNonzeroAmount(stableTknAmount);\n uint256 stableTknAmountUSD = _previewTokenUSDAmount(stableTknAmount, FeeDirection.IN);\n\n //calculate feeIn\n uint256 fee = _calculateFee(stableTknAmountUSD, FeeDirection.IN);\n uint256 vaiToMint = stableTknAmountUSD - fee;\n\n if (vaiMinted + stableTknAmountUSD > vaiMintCap) {\n revert VAIMintCapReached();\n }\n\n return vaiToMint;\n }\n\n /**\n * @dev Calculates the USD value of the given amount of stable tokens depending on the swap direction.\n * @param amount The amount of stable tokens.\n * @param direction The direction of the swap.\n * @return The USD value of the given amount of stable tokens scaled by 1e18 taking into account the direction of the swap\n */\n function _previewTokenUSDAmount(uint256 amount, FeeDirection direction) internal view returns (uint256) {\n return (amount * _getPriceInUSD(direction)) / MANTISSA_ONE;\n }\n\n /**\n * @notice Get the price of stable token in USD.\n * @dev This function returns either min(1$,oraclePrice) or max(1$,oraclePrice) with a decimal scale (36 - asset_decimals). E.g. for 8 decimal token 1$ will be 1e28.\n * @param direction The direction of the swap: FeeDirection.IN or FeeDirection.OUT.\n * @return The price in USD, adjusted based on the selected direction.\n */\n function _getPriceInUSD(FeeDirection direction) internal view returns (uint256) {\n // get price with a scale = (36 - asset_decimals)\n uint256 price = oracle.getPrice(STABLE_TOKEN_ADDRESS);\n\n if (direction == FeeDirection.IN) {\n // MIN(1, price)\n return price < ONE_DOLLAR ? price : ONE_DOLLAR;\n } else {\n // MAX(1, price)\n return price > ONE_DOLLAR ? price : ONE_DOLLAR;\n }\n }\n\n /**\n * @notice Calculate the fee amount based on the input amount and fee percentage.\n * @dev Reverts if the fee percentage calculation results in rounding down to 0.\n * @param amount The input amount to calculate the fee from.\n * @param direction The direction of the fee: FeeDirection.IN or FeeDirection.OUT.\n * @return The fee amount.\n */\n function _calculateFee(uint256 amount, FeeDirection direction) internal view returns (uint256) {\n uint256 feePercent;\n if (direction == FeeDirection.IN) {\n feePercent = feeIn;\n } else {\n feePercent = feeOut;\n }\n if (feePercent == 0) {\n return 0;\n } else {\n // checking if the percent calculation will result in rounding down to 0\n if (amount * feePercent < BASIS_POINTS_DIVISOR) {\n revert AmountTooSmall();\n }\n return (amount * feePercent) / BASIS_POINTS_DIVISOR;\n }\n }\n\n /**\n * @notice Checks that the address is not the zero address.\n * @param someone The address to check.\n */\n function _ensureNonzeroAddress(address someone) private pure {\n if (someone == address(0)) revert ZeroAddress();\n }\n\n /**\n * @notice Checks that the amount passed as stable tokens is bigger than zero\n * @param amount The amount to validate\n */\n function _ensureNonzeroAmount(uint256 amount) private pure {\n if (amount == 0) revert ZeroAmount();\n }\n}\n" + }, + "contracts/Swap/interfaces/CustomErrors.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\n// **************\n// *** ERRORS ***\n// **************\n\n///@notice Error indicating that suplying to a given market failed.\nerror SupplyError(address supplier, address vToken, uint256 errorCode);\n\n///@notice Error indicating that repaying to given market failed.\nerror RepayError(address repayer, address vToken, uint256 errorCode);\n\n///@notice Error indicating wBNB address passed is not the expected one.\nerror WrongAddress(address expectedAdddress, address passedAddress);\n\n///@notice Error thrown when deadline for swap has expired\nerror SwapDeadlineExpire(uint256 deadline, uint256 timestemp);\n\n///@notice Error thrown where the input amount parameter for a token is 0\nerror InsufficientInputAmount();\n\n///@notice Error thrown when the amount out passed is 0\nerror InsufficientOutputAmount();\n\n///@notice Error thrown when the amount received from a trade is below the minimum\nerror OutputAmountBelowMinimum(uint256 amountOut, uint256 amountOutMin);\n\n///@notice Error thrown when the amount In is above the amount in maximum\nerror InputAmountAboveMaximum(uint256 amountIn, uint256 amountIntMax);\n\n///@notice Error thrown when amount is above the msg.value(amountMax)\nerror ExcessiveInputAmount(uint256 amount, uint256 amountMax);\n\n///@notice Error thrown when the given reserves are equal to 0\nerror InsufficientLiquidity();\n\n///@notice Error thrown if a zero address is passed\nerror ZeroAddress();\n\n///@notice Error thrown if two token addresses are identical\nerror IdenticalAddresses();\n\n///@notice Error thrown when the trade path[] parameter consists of only 1 token (i.e. path.length<2)\nerror InvalidPath();\n\n///@notice Error thrown when invalid vToken address is passed to swap router\nerror VTokenNotListed(address vToken);\n\n///@notice Error thrown when invalid underlying is passed as per given vToken\nerror VTokenUnderlyingInvalid(address underlying);\n\n///@notice Error thrown when swapamount is less than the amountOutmin\nerror SwapAmountLessThanAmountOutMin(uint256 swapAmount, uint256 amountOutMin);\n\n///@notice Error thrown when swapRouter's balance is less than sweep amount\nerror InsufficientBalance(uint256 sweepAmount, uint256 balance);\n\n///@notice Error thrown when safeApprove failed\nerror SafeApproveFailed();\n\n///@notice Error thrown when safeTransfer failed\nerror SafeTransferFailed();\n\n///@notice Error thrown when transferFrom failed\nerror SafeTransferFromFailed();\n\n///@notice Error thrown when safeTransferBNB failed\nerror SafeTransferBNBFailed();\n\n///@notice Error thrown when reentrant check fails\nerror ReentrantCheck();\n" + }, + "contracts/Swap/interfaces/InterfaceComptroller.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface InterfaceComptroller {\n function markets(address) external view returns (bool);\n}\n" + }, + "contracts/Swap/interfaces/IPancakePair.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface IPancakePair {\n event Approval(address indexed owner, address indexed spender, uint value);\n event Transfer(address indexed from, address indexed to, uint value);\n\n function name() external pure returns (string memory);\n\n function symbol() external pure returns (string memory);\n\n function decimals() external pure returns (uint8);\n\n function totalSupply() external view returns (uint);\n\n function balanceOf(address owner) external view returns (uint);\n\n function allowance(address owner, address spender) external view returns (uint);\n\n function approve(address spender, uint value) external returns (bool);\n\n function transfer(address to, uint value) external returns (bool);\n\n function transferFrom(address from, address to, uint value) external returns (bool);\n\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n\n function nonces(address owner) external view returns (uint);\n\n function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;\n\n event Mint(address indexed sender, uint amount0, uint amount1);\n event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);\n event Swap(\n address indexed sender,\n uint amount0In,\n uint amount1In,\n uint amount0Out,\n uint amount1Out,\n address indexed to\n );\n event Sync(uint112 reserve0, uint112 reserve1);\n\n function MINIMUM_LIQUIDITY() external pure returns (uint);\n\n function factory() external view returns (address);\n\n function token0() external view returns (address);\n\n function token1() external view returns (address);\n\n function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);\n\n function price0CumulativeLast() external view returns (uint);\n\n function price1CumulativeLast() external view returns (uint);\n\n function kLast() external view returns (uint);\n\n function mint(address to) external returns (uint liquidity);\n\n function burn(address to) external returns (uint amount0, uint amount1);\n\n function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;\n\n function skim(address to) external;\n\n function sync() external;\n\n function initialize(address, address) external;\n}\n" + }, + "contracts/Swap/interfaces/IPancakeSwapV2Factory.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface IPancakeSwapV2Factory {\n event PairCreated(address indexed token0, address indexed token1, address pair, uint);\n\n function feeTo() external view returns (address);\n\n function feeToSetter() external view returns (address);\n\n function getPair(address tokenA, address tokenB) external view returns (address pair);\n\n function allPairs(uint) external view returns (address pair);\n\n function allPairsLength() external view returns (uint);\n\n function createPair(address tokenA, address tokenB) external returns (address pair);\n\n function setFeeTo(address) external;\n\n function setFeeToSetter(address) external;\n}\n" + }, + "contracts/Swap/interfaces/IPancakeSwapV2Router.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface IPancakeSwapV2Router {\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapExactTokensForTokensAtSupportingFee(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256 swapAmount);\n\n function swapExactBNBForTokens(\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable returns (uint256[] memory amounts);\n\n function swapExactBNBForTokensAtSupportingFee(\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable returns (uint256 swapAmount);\n\n function swapExactTokensForBNB(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapExactTokensForBNBAtSupportingFee(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256 swapAmount);\n\n function swapTokensForExactTokens(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapBNBForExactTokens(\n uint256 amountOut,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable returns (uint256[] memory amounts);\n\n function swapTokensForExactBNB(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external returns (uint256[] memory amounts);\n\n function swapExactTokensForTokensAndSupply(\n address vTokenAddress,\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapExactTokensForTokensAndSupplyAtSupportingFee(\n address vTokenAddress,\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapExactBNBForTokensAndSupply(\n address vTokenAddress,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external payable;\n\n function swapExactBNBForTokensAndSupplyAtSupportingFee(\n address vTokenAddress,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external payable;\n\n function swapTokensForExactTokensAndSupply(\n address vTokenAddress,\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapBNBForExactTokensAndSupply(\n address vTokenAddress,\n uint256 amountOut,\n address[] calldata path,\n uint256 deadline\n ) external payable;\n\n function swapExactTokensForBNBAndSupply(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapExactTokensForBNBAndSupplyAtSupportingFee(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapTokensForExactBNBAndSupply(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapBNBForFullTokenDebtAndRepay(\n address vTokenAddress,\n address[] calldata path,\n uint256 deadline\n ) external payable;\n\n function swapExactTokensForTokensAndRepay(\n address vTokenAddress,\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapExactTokensForTokensAndRepayAtSupportingFee(\n address vTokenAddress,\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapExactBNBForTokensAndRepay(\n address vTokenAddress,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external payable;\n\n function swapExactBNBForTokensAndRepayAtSupportingFee(\n address vTokenAddress,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external payable;\n\n function swapTokensForExactTokensAndRepay(\n address vTokenAddress,\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapTokensForFullTokenDebtAndRepay(\n address vTokenAddress,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapBNBForExactTokensAndRepay(\n address vTokenAddress,\n uint256 amountOut,\n address[] calldata path,\n uint256 deadline\n ) external payable;\n\n function swapExactTokensForBNBAndRepay(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapExactTokensForBNBAndRepayAtSupportingFee(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapTokensForExactBNBAndRepay(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external;\n\n function swapTokensForFullBNBDebtAndRepay(uint256 amountInMax, address[] calldata path, uint256 deadline) external;\n}\n" + }, + "contracts/Swap/interfaces/IVBNB.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface IVBNB {\n function repayBorrowBehalf(address borrower) external payable;\n\n function mint() external payable;\n\n function balanceOf(address owner) external view returns (uint256);\n}\n" + }, + "contracts/Swap/interfaces/IVtoken.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface IVToken {\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\n\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\n\n function borrowBalanceCurrent(address account) external returns (uint);\n\n function underlying() external returns (address);\n}\n" + }, + "contracts/Swap/interfaces/IWBNB.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IWBNB {\n function deposit() external payable;\n\n function transfer(address to, uint value) external returns (bool);\n\n function withdraw(uint) external;\n\n function balanceOf(address owner) external view returns (uint256 balance);\n}\n" + }, + "contracts/Swap/IRouterHelper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface IRouterHelper {\n function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) external pure returns (uint256 amountB);\n\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) external pure returns (uint256 amountOut);\n\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) external pure returns (uint256 amountIn);\n\n function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);\n\n function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts);\n}\n" + }, + "contracts/Swap/lib/PancakeLibrary.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.25;\n\nimport \"../interfaces/IPancakePair.sol\";\nimport \"../interfaces/CustomErrors.sol\";\n\nlibrary PancakeLibrary {\n /**\n * @notice Used to handle return values from pairs sorted in this order\n * @param tokenA The address of token A\n * @param tokenB The address of token B\n * @return token0 token1 Sorted token addresses\n **/\n function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {\n if (tokenA == tokenB) {\n revert IdenticalAddresses();\n }\n (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);\n if (token0 == address(0)) {\n revert ZeroAddress();\n }\n }\n\n /**\n * @notice Calculates the CREATE2 address for a pair without making any external calls\n * @param factory Address of the pancake swap factory\n * @param tokenA The address of token A\n * @param tokenB The address of token B\n * @return pair Address for a pair\n **/\n function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {\n (address token0, address token1) = sortTokens(tokenA, tokenB);\n pair = address(\n uint160(\n uint256(\n keccak256(\n abi.encodePacked(\n hex\"ff\",\n factory,\n keccak256(abi.encodePacked(token0, token1)),\n hex\"00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5\" // init code hash\n )\n )\n )\n )\n );\n }\n\n /**\n * @notice Fetches and sorts the reserves for a pair\n * @param factory Address of the pancake swap factory\n * @param tokenA The address of token A\n * @param tokenB The address of token B\n * @return reserveA reserveB Reserves for the token A and token B\n **/\n function getReserves(\n address factory,\n address tokenA,\n address tokenB\n ) internal view returns (uint256 reserveA, uint256 reserveB) {\n (address token0, ) = sortTokens(tokenA, tokenB);\n address pairAddress = pairFor(factory, tokenA, tokenB);\n (uint256 reserve0, uint256 reserve1, ) = IPancakePair(pairAddress).getReserves();\n (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);\n }\n\n /**\n * @notice Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n * @param amountA The amount of token A\n * @param reserveA The amount of reserves for token A before swap\n * @param reserveB The amount of reserves for token B before swap\n * @return amountB An equivalent amount of the token B\n **/\n function quote(uint256 amountA, uint256 reserveA, uint256 reserveB) internal pure returns (uint256 amountB) {\n if (amountA == 0) {\n revert InsufficientInputAmount();\n } else if (reserveA == 0 || reserveB == 0) {\n revert InsufficientLiquidity();\n }\n amountB = (amountA * reserveB) / reserveA;\n }\n\n /**\n * @notice Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n * @param amountIn The amount of token A need to swap\n * @param reserveIn The amount of reserves for token A before swap\n * @param reserveOut The amount of reserves for token B after swap\n * @return amountOut The maximum output amount of the token B\n **/\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountOut) {\n if (amountIn == 0) {\n revert InsufficientInputAmount();\n } else if (reserveIn == 0 || reserveOut == 0) {\n revert InsufficientLiquidity();\n }\n uint256 amountInWithFee = amountIn * 9975;\n uint256 numerator = amountInWithFee * reserveOut;\n uint256 denominator = (reserveIn * 10000) + amountInWithFee;\n amountOut = numerator / denominator;\n }\n\n /**\n * @notice Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n * @param amountOut The amount of token B after swap\n * @param reserveIn The amount of reserves for token A before swap\n * @param reserveOut The amount of reserves for token B after swap\n * @return amountIn Required input amount of the token A\n **/\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) internal pure returns (uint256 amountIn) {\n if (amountOut == 0) {\n revert InsufficientOutputAmount();\n } else if (reserveIn == 0 || reserveOut == 0) {\n revert InsufficientLiquidity();\n }\n uint256 numerator = reserveIn * amountOut * 10000;\n uint256 denominator = (reserveOut - amountOut) * 9975;\n amountIn = (numerator / denominator) + 1;\n }\n\n /**\n * @notice Performs chained getAmountOut calculations on any number of pairs\n * @param factory Address of the pancake swap factory\n * @param amountIn The amount of tokens to swap.\n * @param path Array with addresses of the underlying assets to be swapped\n * @return amounts Array of amounts after performing swap for respective pairs in path\n **/\n function getAmountsOut(\n address factory,\n uint256 amountIn,\n address[] memory path\n ) internal view returns (uint256[] memory amounts) {\n if (path.length <= 1) {\n revert InvalidPath();\n }\n amounts = new uint256[](path.length);\n amounts[0] = amountIn;\n for (uint256 i; i < path.length - 1; ) {\n (uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i], path[i + 1]);\n amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);\n unchecked {\n i += 1;\n }\n }\n }\n\n /**\n * @notice Performs chained getAmountIn calculations on any number of pairs\n * @param factory Address of the pancake swap factory\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param path Array with addresses of the underlying assets to be swapped\n * @return amounts Array of amounts after performing swap for respective pairs in path\n **/\n function getAmountsIn(\n address factory,\n uint256 amountOut,\n address[] memory path\n ) internal view returns (uint256[] memory amounts) {\n if (path.length <= 1) {\n revert InvalidPath();\n }\n amounts = new uint256[](path.length);\n amounts[amounts.length - 1] = amountOut;\n for (uint256 i = path.length - 1; i > 0; ) {\n (uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i - 1], path[i]);\n amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);\n unchecked {\n i -= 1;\n }\n }\n }\n}\n" + }, + "contracts/Swap/lib/TransferHelper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.25;\n\nimport \"../interfaces/CustomErrors.sol\";\n\n// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false\nlibrary TransferHelper {\n /**\n * @dev `value` as the allowance of `spender` over the caller's tokens.\n * @param token Address of the token\n * @param to Address of the spender\n * @param value Amount as allowance\n */\n function safeApprove(address token, address to, uint256 value) internal {\n // bytes4(keccak256(bytes('approve(address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));\n if (!(success && (data.length == 0 || abi.decode(data, (bool))))) {\n revert SafeApproveFailed();\n }\n }\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 * @param token Address of the token\n * @param to Address of the receiver\n * @param value Amount need to transfer\n */\n function safeTransfer(address token, address to, uint256 value) internal {\n // bytes4(keccak256(bytes('transfer(address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));\n if (!(success && (data.length == 0 || abi.decode(data, (bool))))) {\n revert SafeTransferFailed();\n }\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 * @param token Address of the token\n * @param from Address of the asset'sowner\n * @param to Address of the receiver\n * @param value Amount need to transfer\n */\n function safeTransferFrom(address token, address from, address to, uint256 value) internal {\n // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));\n (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));\n if (!(success && (data.length == 0 || abi.decode(data, (bool))))) {\n revert SafeTransferFromFailed();\n }\n }\n\n /**\n * @dev Transfer `value` amount of `BNB` from the calling contract to `to`. If `token` returns no value,\n * non-reverting calls are assumed to be successful.\n * @param to Address of the receiver\n * @param value Amount need to transfer\n */\n function safeTransferBNB(address to, uint256 value) internal {\n (bool success, ) = to.call{ value: value }(new bytes(0));\n if (!success) {\n revert SafeTransferBNBFailed();\n }\n }\n}\n" + }, + "contracts/Swap/RouterHelper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport \"./lib/PancakeLibrary.sol\";\nimport \"./interfaces/IWBNB.sol\";\nimport \"./lib/TransferHelper.sol\";\n\nimport \"./interfaces/CustomErrors.sol\";\nimport \"./IRouterHelper.sol\";\n\nabstract contract RouterHelper is IRouterHelper {\n /// @notice Select the type of Token for which either a supporting fee would be deducted or not at the time of transfer.\n enum TypesOfTokens {\n NON_SUPPORTING_FEE,\n SUPPORTING_FEE\n }\n\n /// @notice Address of WBNB contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WBNB;\n\n /// @notice Address of pancake swap factory contract.\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable factory;\n\n // **************\n // *** EVENTS ***\n // **************\n /// @notice This event is emitted whenever a successful swap (tokenA -> tokenB) occurs\n event SwapTokensForTokens(address indexed swapper, address[] indexed path, uint256[] indexed amounts);\n\n /// @notice This event is emitted whenever a successful swap (tokenA -> tokenB) occurs\n event SwapTokensForTokensAtSupportingFee(address indexed swapper, address[] indexed path);\n\n /// @notice This event is emitted whenever a successful swap (BNB -> token) occurs\n event SwapBnbForTokens(address indexed swapper, address[] indexed path, uint256[] indexed amounts);\n\n /// @notice This event is emitted whenever a successful swap (BNB -> token) occurs\n event SwapBnbForTokensAtSupportingFee(address indexed swapper, address[] indexed path);\n\n /// @notice This event is emitted whenever a successful swap (token -> BNB) occurs\n event SwapTokensForBnb(address indexed swapper, address[] indexed path, uint256[] indexed amounts);\n\n /// @notice This event is emitted whenever a successful swap (token -> BNB) occurs\n event SwapTokensForBnbAtSupportingFee(address indexed swapper, address[] indexed path);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address WBNB_, address factory_) {\n if (WBNB_ == address(0) || factory_ == address(0)) {\n revert ZeroAddress();\n }\n WBNB = WBNB_;\n factory = factory_;\n }\n\n /**\n * @notice Perform swap on the path(pairs)\n * @param amounts Araay of amounts of tokens after performing the swap\n * @param path Array with addresses of the underlying assets to be swapped\n * @param _to Recipient of the output tokens.\n */\n function _swap(uint256[] memory amounts, address[] memory path, address _to) internal virtual {\n for (uint256 i; i < path.length - 1; ) {\n (address input, address output) = (path[i], path[i + 1]);\n (address token0, ) = PancakeLibrary.sortTokens(input, output);\n uint256 amountOut = amounts[i + 1];\n (uint256 amount0Out, uint256 amount1Out) = input == token0\n ? (uint256(0), amountOut)\n : (amountOut, uint256(0));\n address to = i < path.length - 2 ? PancakeLibrary.pairFor(factory, output, path[i + 2]) : _to;\n IPancakePair(PancakeLibrary.pairFor(factory, input, output)).swap(amount0Out, amount1Out, to, new bytes(0));\n unchecked {\n i += 1;\n }\n }\n }\n\n // **** SWAP (supporting fee-on-transfer tokens) ****\n\n /**\n * @notice Perform swap on the path(pairs) for supporting fee\n * @dev requires the initial amount to have already been sent to the first pair\n * @param path Array with addresses of the underlying assets to be swapped\n * @param _to Recipient of the output tokens.\n */\n function _swapSupportingFeeOnTransferTokens(address[] memory path, address _to) internal virtual {\n for (uint256 i; i < path.length - 1; ) {\n (address input, address output) = (path[i], path[i + 1]);\n (address token0, ) = PancakeLibrary.sortTokens(input, output);\n IPancakePair pair = IPancakePair(PancakeLibrary.pairFor(factory, input, output));\n uint256 amountInput;\n uint256 amountOutput;\n {\n // scope to avoid stack too deep errors\n (uint256 reserve0, uint256 reserve1, ) = pair.getReserves();\n (uint256 reserveInput, uint256 reserveOutput) = input == token0\n ? (reserve0, reserve1)\n : (reserve1, reserve0);\n\n uint256 balance = IERC20(input).balanceOf(address(pair));\n amountInput = balance - reserveInput;\n amountOutput = PancakeLibrary.getAmountOut(amountInput, reserveInput, reserveOutput);\n }\n (uint256 amount0Out, uint256 amount1Out) = input == token0\n ? (uint256(0), amountOutput)\n : (amountOutput, uint256(0));\n address to = i < path.length - 2 ? PancakeLibrary.pairFor(factory, output, path[i + 2]) : _to;\n pair.swap(amount0Out, amount1Out, to, new bytes(0));\n unchecked {\n i += 1;\n }\n }\n }\n\n /**\n * @notice Swap token A for token B\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param swapFor TypesOfTokens, either supporing fee or non supporting fee\n * @return amounts Array of amounts after performing swap for respective pairs in path\n */\n function _swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n TypesOfTokens swapFor\n ) internal returns (uint256[] memory amounts) {\n address pairAddress = PancakeLibrary.pairFor(factory, path[0], path[1]);\n if (swapFor == TypesOfTokens.NON_SUPPORTING_FEE) {\n amounts = PancakeLibrary.getAmountsOut(factory, amountIn, path);\n if (amounts[amounts.length - 1] < amountOutMin) {\n revert OutputAmountBelowMinimum(amounts[amounts.length - 1], amountOutMin);\n }\n TransferHelper.safeTransferFrom(path[0], msg.sender, pairAddress, amounts[0]);\n _swap(amounts, path, to);\n emit SwapTokensForTokens(msg.sender, path, amounts);\n } else {\n TransferHelper.safeTransferFrom(path[0], msg.sender, pairAddress, amountIn);\n _swapSupportingFeeOnTransferTokens(path, to);\n emit SwapTokensForTokensAtSupportingFee(msg.sender, path);\n }\n }\n\n /**\n * @notice Swap exact BNB for token\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param swapFor TypesOfTokens, either supporing fee or non supporting fee\n * @return amounts Array of amounts after performing swap for respective pairs in path\n */\n function _swapExactBNBForTokens(\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n TypesOfTokens swapFor\n ) internal returns (uint256[] memory amounts) {\n address wBNBAddress = WBNB;\n if (path[0] != wBNBAddress) {\n revert WrongAddress(wBNBAddress, path[0]);\n }\n IWBNB(wBNBAddress).deposit{ value: msg.value }();\n TransferHelper.safeTransfer(wBNBAddress, PancakeLibrary.pairFor(factory, path[0], path[1]), msg.value);\n if (swapFor == TypesOfTokens.NON_SUPPORTING_FEE) {\n amounts = PancakeLibrary.getAmountsOut(factory, msg.value, path);\n if (amounts[amounts.length - 1] < amountOutMin) {\n revert OutputAmountBelowMinimum(amounts[amounts.length - 1], amountOutMin);\n }\n _swap(amounts, path, to);\n emit SwapBnbForTokens(msg.sender, path, amounts);\n } else {\n _swapSupportingFeeOnTransferTokens(path, to);\n emit SwapBnbForTokensAtSupportingFee(msg.sender, path);\n }\n }\n\n /**\n * @notice Swap token A for BNB\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of BNB to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param swapFor TypesOfTokens, either supporing fee or non supporting fee\n * @return amounts Array of amounts after performing swap for respective pairs in path\n */\n function _swapExactTokensForBNB(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n TypesOfTokens swapFor\n ) internal returns (uint256[] memory amounts) {\n if (path[path.length - 1] != WBNB) {\n revert WrongAddress(WBNB, path[path.length - 1]);\n }\n uint256 WBNBAmount;\n if (swapFor == TypesOfTokens.NON_SUPPORTING_FEE) {\n amounts = PancakeLibrary.getAmountsOut(factory, amountIn, path);\n if (amounts[amounts.length - 1] < amountOutMin) {\n revert OutputAmountBelowMinimum(amounts[amounts.length - 1], amountOutMin);\n }\n TransferHelper.safeTransferFrom(\n path[0],\n msg.sender,\n PancakeLibrary.pairFor(factory, path[0], path[1]),\n amounts[0]\n );\n _swap(amounts, path, address(this));\n WBNBAmount = amounts[amounts.length - 1];\n } else {\n uint256 balanceBefore = IWBNB(WBNB).balanceOf(address(this));\n TransferHelper.safeTransferFrom(\n path[0],\n msg.sender,\n PancakeLibrary.pairFor(factory, path[0], path[1]),\n amountIn\n );\n _swapSupportingFeeOnTransferTokens(path, address(this));\n uint256 balanceAfter = IWBNB(WBNB).balanceOf(address(this));\n WBNBAmount = balanceAfter - balanceBefore;\n }\n IWBNB(WBNB).withdraw(WBNBAmount);\n if (to != address(this)) {\n TransferHelper.safeTransferBNB(to, WBNBAmount);\n }\n if (swapFor == TypesOfTokens.NON_SUPPORTING_FEE) {\n emit SwapTokensForBnb(msg.sender, path, amounts);\n } else {\n emit SwapTokensForBnbAtSupportingFee(msg.sender, path);\n }\n }\n\n /**\n * @notice Swap token A for exact amount of token B\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @return amounts Array of amounts after performing swap for respective pairs in path\n **/\n function _swapTokensForExactTokens(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to\n ) internal returns (uint256[] memory amounts) {\n amounts = PancakeLibrary.getAmountsIn(factory, amountOut, path);\n if (amounts[0] > amountInMax) {\n revert InputAmountAboveMaximum(amounts[0], amountInMax);\n }\n TransferHelper.safeTransferFrom(\n path[0],\n msg.sender,\n PancakeLibrary.pairFor(factory, path[0], path[1]),\n amounts[0]\n );\n _swap(amounts, path, to);\n emit SwapTokensForTokens(msg.sender, path, amounts);\n }\n\n /**\n * @notice Swap BNB for exact amount of token B\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @return amounts Array of amounts after performing swap for respective pairs in path\n **/\n function _swapBNBForExactTokens(\n uint256 amountOut,\n address[] calldata path,\n address to\n ) internal returns (uint256[] memory amounts) {\n if (path[0] != WBNB) {\n revert WrongAddress(WBNB, path[0]);\n }\n amounts = PancakeLibrary.getAmountsIn(factory, amountOut, path);\n if (amounts[0] > msg.value) {\n revert ExcessiveInputAmount(amounts[0], msg.value);\n }\n IWBNB(WBNB).deposit{ value: amounts[0] }();\n TransferHelper.safeTransfer(WBNB, PancakeLibrary.pairFor(factory, path[0], path[1]), amounts[0]);\n _swap(amounts, path, to);\n // refund dust BNB, if any\n if (msg.value > amounts[0]) TransferHelper.safeTransferBNB(msg.sender, msg.value - amounts[0]);\n emit SwapBnbForTokens(msg.sender, path, amounts);\n }\n\n /**\n * @notice Swap token A for exact BNB\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @return amounts Array of amounts after performing swap for respective pairs in path\n **/\n function _swapTokensForExactBNB(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to\n ) internal returns (uint256[] memory amounts) {\n if (path[path.length - 1] != WBNB) {\n revert WrongAddress(WBNB, path[path.length - 1]);\n }\n amounts = PancakeLibrary.getAmountsIn(factory, amountOut, path);\n if (amounts[0] > amountInMax) {\n revert InputAmountAboveMaximum(amounts[amounts.length - 1], amountInMax);\n }\n TransferHelper.safeTransferFrom(\n path[0],\n msg.sender,\n PancakeLibrary.pairFor(factory, path[0], path[1]),\n amounts[0]\n );\n _swap(amounts, path, address(this));\n IWBNB(WBNB).withdraw(amounts[amounts.length - 1]);\n if (to != address(this)) {\n TransferHelper.safeTransferBNB(to, amounts[amounts.length - 1]);\n }\n emit SwapTokensForBnb(msg.sender, path, amounts);\n }\n\n // **** LIBRARY FUNCTIONS ****\n\n /**\n * @notice Given some amount of an asset and pair reserves, returns an equivalent amount of the other asset\n * @param amountA The amount of token A\n * @param reserveA The amount of reserves for token A before swap\n * @param reserveB The amount of reserves for token B before swap\n * @return amountB An equivalent amount of the token B\n **/\n function quote(\n uint256 amountA,\n uint256 reserveA,\n uint256 reserveB\n ) external pure virtual override returns (uint256 amountB) {\n return PancakeLibrary.quote(amountA, reserveA, reserveB);\n }\n\n /**\n * @notice Given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset\n * @param amountIn The amount of token A need to swap\n * @param reserveIn The amount of reserves for token A before swap\n * @param reserveOut The amount of reserves for token B after swap\n * @return amountOut The maximum output amount of the token B\n **/\n function getAmountOut(\n uint256 amountIn,\n uint256 reserveIn,\n uint256 reserveOut\n ) external pure virtual override returns (uint256 amountOut) {\n return PancakeLibrary.getAmountOut(amountIn, reserveIn, reserveOut);\n }\n\n /**\n * @notice Given an output amount of an asset and pair reserves, returns a required input amount of the other asset\n * @param amountOut The amount of token B after swap\n * @param reserveIn The amount of reserves for token A before swap\n * @param reserveOut The amount of reserves for token B after swap\n * @return amountIn Required input amount of the token A\n **/\n function getAmountIn(\n uint256 amountOut,\n uint256 reserveIn,\n uint256 reserveOut\n ) external pure virtual override returns (uint256 amountIn) {\n return PancakeLibrary.getAmountIn(amountOut, reserveIn, reserveOut);\n }\n\n /**\n * @notice performs chained getAmountOut calculations on any number of pairs.\n * @param amountIn The amount of tokens to swap.\n * @param path Array with addresses of the underlying assets to be swapped.\n */\n function getAmountsOut(\n uint256 amountIn,\n address[] memory path\n ) external view virtual override returns (uint256[] memory amounts) {\n return PancakeLibrary.getAmountsOut(factory, amountIn, path);\n }\n\n /**\n * @notice performs chained getAmountIn calculations on any number of pairs.\n * @param amountOut amountOut The amount of the tokens needs to be as output token.\n * @param path Array with addresses of the underlying assets to be swapped.\n */\n function getAmountsIn(\n uint256 amountOut,\n address[] memory path\n ) external view virtual override returns (uint256[] memory amounts) {\n return PancakeLibrary.getAmountsIn(factory, amountOut, path);\n }\n}\n" + }, + "contracts/Swap/SwapRouter.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity 0.8.25;\n\nimport \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"./interfaces/IPancakeSwapV2Router.sol\";\nimport \"./interfaces/IVtoken.sol\";\nimport \"./RouterHelper.sol\";\nimport \"./interfaces/IVBNB.sol\";\nimport \"./interfaces/IVtoken.sol\";\nimport \"./interfaces/InterfaceComptroller.sol\";\n\n/**\n * @title Venus's Pancake Swap Integration Contract\n * @notice This contracts allows users to swap a token for another one and supply/repay with the latter.\n * @dev For all functions that do not swap native BNB, user must approve this contract with the amount, prior the calling the swap function.\n * @author 0xlucian\n */\n\ncontract SwapRouter is Ownable2Step, RouterHelper, IPancakeSwapV2Router {\n using SafeERC20 for IERC20;\n\n address public immutable comptrollerAddress;\n\n uint256 private constant _NOT_ENTERED = 1;\n\n uint256 private constant _ENTERED = 2;\n\n address public vBNBAddress;\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n uint256 internal _status;\n\n // ***************\n // ** MODIFIERS **\n // ***************\n modifier ensure(uint256 deadline) {\n if (deadline < block.timestamp) {\n revert SwapDeadlineExpire(deadline, block.timestamp);\n }\n _;\n }\n\n modifier ensurePath(address[] calldata path) {\n if (path.length < 2) {\n revert InvalidPath();\n }\n _;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n if (_status == _ENTERED) {\n revert ReentrantCheck();\n }\n _status = _ENTERED;\n _;\n _status = _NOT_ENTERED;\n }\n\n /// @notice event emitted on sweep token success\n event SweepToken(address indexed token, address indexed to, uint256 sweepAmount);\n\n /// @notice event emitted on vBNBAddress update\n event VBNBAddressUpdated(address indexed oldAddress, address indexed newAddress);\n\n // *********************\n // **** CONSTRUCTOR ****\n // *********************\n\n /// @notice Constructor for the implementation contract. Sets immutable variables.\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address WBNB_,\n address factory_,\n address _comptrollerAddress,\n address _vBNBAddress\n ) RouterHelper(WBNB_, factory_) {\n if (_comptrollerAddress == address(0) || _vBNBAddress == address(0)) {\n revert ZeroAddress();\n }\n comptrollerAddress = _comptrollerAddress;\n _status = _NOT_ENTERED;\n vBNBAddress = _vBNBAddress;\n }\n\n receive() external payable {\n assert(msg.sender == WBNB); // only accept BNB via fallback from the WBNB contract\n }\n\n // ****************************\n // **** EXTERNAL FUNCTIONS ****\n // ****************************\n\n /**\n * @notice Setter for the vBNB address.\n * @param _vBNBAddress Address of the BNB vToken to update.\n */\n function setVBNBAddress(address _vBNBAddress) external onlyOwner {\n if (_vBNBAddress == address(0)) {\n revert ZeroAddress();\n }\n\n _isVTokenListed(_vBNBAddress);\n\n address oldAddress = vBNBAddress;\n vBNBAddress = _vBNBAddress;\n\n emit VBNBAddressUpdated(oldAddress, vBNBAddress);\n }\n\n /**\n * @notice Swap token A for token B and supply to a Venus market\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n */\n function swapExactTokensForTokensAndSupply(\n address vTokenAddress,\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapExactTokensForTokens(amountIn, amountOutMin, path, address(this), TypesOfTokens.NON_SUPPORTING_FEE);\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _supply(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap deflationary (a small amount of fee is deducted at the time of transfer of token) token A for token B and supply to a Venus market.\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n */\n function swapExactTokensForTokensAndSupplyAtSupportingFee(\n address vTokenAddress,\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapExactTokensForTokens(amountIn, amountOutMin, path, address(this), TypesOfTokens.SUPPORTING_FEE);\n uint256 swapAmount = _checkForAmountOut(lastAsset, balanceBefore, amountOutMin, address(this));\n _supply(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap BNB for another token and supply to a Venus market\n * @dev The amount to be swapped is obtained from the msg.value, since we are swapping BNB\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapExactBNBForTokensAndSupply(\n address vTokenAddress,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external payable override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapExactBNBForTokens(amountOutMin, path, address(this), TypesOfTokens.NON_SUPPORTING_FEE);\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _supply(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap BNB for another deflationary token (a small amount of fee is deducted at the time of transfer of token) and supply to a Venus market\n * @dev The amount to be swapped is obtained from the msg.value, since we are swapping BNB\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapExactBNBForTokensAndSupplyAtSupportingFee(\n address vTokenAddress,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external payable override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapExactBNBForTokens(amountOutMin, path, address(this), TypesOfTokens.SUPPORTING_FEE);\n uint256 swapAmount = _checkForAmountOut(lastAsset, balanceBefore, amountOutMin, address(this));\n _supply(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap tokens for Exact tokens and supply to a Venus market\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapTokensForExactTokensAndSupply(\n address vTokenAddress,\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapTokensForExactTokens(amountOut, amountInMax, path, address(this));\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _supply(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap BNB for Exact tokens and supply to a Venus market\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapBNBForExactTokensAndSupply(\n address vTokenAddress,\n uint256 amountOut,\n address[] calldata path,\n uint256 deadline\n ) external payable override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapBNBForExactTokens(amountOut, path, address(this));\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _supply(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap Exact tokens for BNB and supply to a Venus market\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapExactTokensForBNBAndSupply(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n uint256 balanceBefore = address(this).balance;\n _swapExactTokensForBNB(amountIn, amountOutMin, path, address(this), TypesOfTokens.NON_SUPPORTING_FEE);\n uint256 balanceAfter = address(this).balance;\n uint256 swapAmount = balanceAfter - balanceBefore;\n _mintVBNBandTransfer(swapAmount);\n }\n\n /**\n * @notice Swap Exact deflationary tokens (a small amount of fee is deducted at the time of transfer of tokens) for BNB and supply to a Venus market\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapExactTokensForBNBAndSupplyAtSupportingFee(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n uint256 balanceBefore = address(this).balance;\n _swapExactTokensForBNB(amountIn, amountOutMin, path, address(this), TypesOfTokens.SUPPORTING_FEE);\n uint256 balanceAfter = address(this).balance;\n uint256 swapAmount = balanceAfter - balanceBefore;\n if (swapAmount < amountOutMin) {\n revert SwapAmountLessThanAmountOutMin(swapAmount, amountOutMin);\n }\n _mintVBNBandTransfer(swapAmount);\n }\n\n /**\n * @notice Swap tokens for Exact BNB and supply to a Venus market\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapTokensForExactBNBAndSupply(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n uint256 balanceBefore = address(this).balance;\n _swapTokensForExactBNB(amountOut, amountInMax, path, address(this));\n uint256 balanceAfter = address(this).balance;\n uint256 swapAmount = balanceAfter - balanceBefore;\n _mintVBNBandTransfer(swapAmount);\n }\n\n /**\n * @notice Swap token A for token B and repay a borrow from a Venus market\n * @param vTokenAddress The address of the vToken contract to repay.\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive (and repay)\n */\n function swapExactTokensForTokensAndRepay(\n address vTokenAddress,\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapExactTokensForTokens(amountIn, amountOutMin, path, address(this), TypesOfTokens.NON_SUPPORTING_FEE);\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _repay(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap deflationary token (a small amount of fee is deducted at the time of transfer of token) token A for token B and repay a borrow from a Venus market\n * @param vTokenAddress The address of the vToken contract to repay.\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive (and repay)\n */\n function swapExactTokensForTokensAndRepayAtSupportingFee(\n address vTokenAddress,\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapExactTokensForTokens(amountIn, amountOutMin, path, address(this), TypesOfTokens.SUPPORTING_FEE);\n uint256 swapAmount = _checkForAmountOut(lastAsset, balanceBefore, amountOutMin, address(this));\n _repay(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap BNB for another token and repay a borrow from a Venus market\n * @dev The amount to be swapped is obtained from the msg.value, since we are swapping BNB\n * @param vTokenAddress The address of the vToken contract to repay.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered so the swap path tokens are listed first and last asset is the token we receive\n */\n function swapExactBNBForTokensAndRepay(\n address vTokenAddress,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external payable override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapExactBNBForTokens(amountOutMin, path, address(this), TypesOfTokens.NON_SUPPORTING_FEE);\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _repay(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap BNB for another deflationary token (a small amount of fee is deducted at the time of transfer of token) and repay a borrow from a Venus market\n * @dev The amount to be swapped is obtained from the msg.value, since we are swapping BNB\n * @param vTokenAddress The address of the vToken contract to repay.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered so the swap path tokens are listed first and last asset is the token we receive\n */\n function swapExactBNBForTokensAndRepayAtSupportingFee(\n address vTokenAddress,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external payable override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapExactBNBForTokens(amountOutMin, path, address(this), TypesOfTokens.SUPPORTING_FEE);\n uint256 swapAmount = _checkForAmountOut(lastAsset, balanceBefore, amountOutMin, address(this));\n _repay(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap tokens for Exact tokens and repay to a Venus market\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapTokensForExactTokensAndRepay(\n address vTokenAddress,\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapTokensForExactTokens(amountOut, amountInMax, path, address(this));\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _repay(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap tokens for full tokens debt and repay to a Venus market\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapTokensForFullTokenDebtAndRepay(\n address vTokenAddress,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n uint256 amountOut = IVToken(vTokenAddress).borrowBalanceCurrent(msg.sender);\n _swapTokensForExactTokens(amountOut, amountInMax, path, address(this));\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _repay(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap BNB for Exact tokens and repay to a Venus market\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapBNBForExactTokensAndRepay(\n address vTokenAddress,\n uint256 amountOut,\n address[] calldata path,\n uint256 deadline\n ) external payable override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n _swapBNBForExactTokens(amountOut, path, address(this));\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _repay(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap BNB for Exact tokens and repay to a Venus market\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapBNBForFullTokenDebtAndRepay(\n address vTokenAddress,\n address[] calldata path,\n uint256 deadline\n ) external payable override nonReentrant ensure(deadline) ensurePath(path) {\n _ensureVTokenChecks(vTokenAddress, path[path.length - 1]);\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(address(this));\n uint256 amountOut = IVToken(vTokenAddress).borrowBalanceCurrent(msg.sender);\n _swapBNBForExactTokens(amountOut, path, address(this));\n uint256 swapAmount = _getSwapAmount(lastAsset, balanceBefore);\n _repay(lastAsset, vTokenAddress, swapAmount);\n }\n\n /**\n * @notice Swap Exact tokens for BNB and repay to a Venus market\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapExactTokensForBNBAndRepay(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n uint256 balanceBefore = address(this).balance;\n _swapExactTokensForBNB(amountIn, amountOutMin, path, address(this), TypesOfTokens.NON_SUPPORTING_FEE);\n uint256 balanceAfter = address(this).balance;\n uint256 swapAmount = balanceAfter - balanceBefore;\n IVBNB(vBNBAddress).repayBorrowBehalf{ value: swapAmount }(msg.sender);\n }\n\n /**\n * @notice Swap Exact deflationary tokens (a small amount of fee is deducted at the time of transfer of tokens) for BNB and repay to a Venus market\n * @param amountIn The amount of tokens to swap.\n * @param amountOutMin Minimum amount of tokens to receive.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapExactTokensForBNBAndRepayAtSupportingFee(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n uint256 balanceBefore = address(this).balance;\n _swapExactTokensForBNB(amountIn, amountOutMin, path, address(this), TypesOfTokens.SUPPORTING_FEE);\n uint256 balanceAfter = address(this).balance;\n uint256 swapAmount = balanceAfter - balanceBefore;\n if (swapAmount < amountOutMin) {\n revert SwapAmountLessThanAmountOutMin(swapAmount, amountOutMin);\n }\n IVBNB(vBNBAddress).repayBorrowBehalf{ value: swapAmount }(msg.sender);\n }\n\n /**\n * @notice Swap tokens for Exact BNB and repay to a Venus market\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapTokensForExactBNBAndRepay(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n uint256 balanceBefore = address(this).balance;\n _swapTokensForExactBNB(amountOut, amountInMax, path, address(this));\n uint256 balanceAfter = address(this).balance;\n uint256 swapAmount = balanceAfter - balanceBefore;\n IVBNB(vBNBAddress).repayBorrowBehalf{ value: swapAmount }(msg.sender);\n }\n\n /**\n * @notice Swap tokens for Exact BNB and repay to a Venus market\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param deadline Unix timestamp after which the transaction will revert.\n * @dev Addresses of underlying assets should be ordered that first asset is the token we are swapping and second asset is the token we receive\n * @dev In case of swapping native BNB the first asset in path array should be the wBNB address\n */\n function swapTokensForFullBNBDebtAndRepay(\n uint256 amountInMax,\n address[] calldata path,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) {\n uint256 balanceBefore = address(this).balance;\n uint256 amountOut = IVToken(vBNBAddress).borrowBalanceCurrent(msg.sender);\n _swapTokensForExactBNB(amountOut, amountInMax, path, address(this));\n uint256 balanceAfter = address(this).balance;\n uint256 swapAmount = balanceAfter - balanceBefore;\n IVBNB(vBNBAddress).repayBorrowBehalf{ value: swapAmount }(msg.sender);\n }\n\n /**\n * @notice Swaps an exact amount of input tokens for as many output tokens as possible,\n * along the route determined by the path. The first element of path is the input token,\n * the last is the output token, and any intermediate elements represent intermediate\n * pairs to trade through (if, for example, a direct pair does not exist).\n * @dev msg.sender should have already given the router an allowance of at least amountIn on the input token.\n * @param amountIn The address of the vToken contract to repay.\n * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n */\n function swapExactTokensForTokens(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external virtual override nonReentrant ensure(deadline) ensurePath(path) returns (uint256[] memory amounts) {\n amounts = _swapExactTokensForTokens(amountIn, amountOutMin, path, to, TypesOfTokens.NON_SUPPORTING_FEE);\n }\n\n /**\n * @notice Swaps an exact amount of input tokens for as many output tokens as possible,\n * along the route determined by the path. The first element of path is the input token,\n * the last is the output token, and any intermediate elements represent intermediate\n * pairs to trade through (if, for example, a direct pair does not exist).\n * This method to swap deflationary tokens which would require supporting fee.\n * @dev msg.sender should have already given the router an allowance of at least amountIn on the input token.\n * @param amountIn The address of the vToken contract to repay.\n * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n */\n function swapExactTokensForTokensAtSupportingFee(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external virtual override nonReentrant ensure(deadline) ensurePath(path) returns (uint256 swapAmount) {\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(to);\n _swapExactTokensForTokens(amountIn, amountOutMin, path, to, TypesOfTokens.SUPPORTING_FEE);\n swapAmount = _checkForAmountOut(lastAsset, balanceBefore, amountOutMin, to);\n }\n\n /**\n * @notice Swaps an exact amount of BNB for as many output tokens as possible,\n * along the route determined by the path. The first element of path must be WBNB,\n * the last is the output token, and any intermediate elements represent\n * intermediate pairs to trade through (if, for example, a direct pair does not exist).\n * @dev amountIn is passed through the msg.value of the transaction\n * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n */\n function swapExactBNBForTokens(\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n )\n external\n payable\n virtual\n override\n nonReentrant\n ensure(deadline)\n ensurePath(path)\n returns (uint256[] memory amounts)\n {\n amounts = _swapExactBNBForTokens(amountOutMin, path, to, TypesOfTokens.NON_SUPPORTING_FEE);\n }\n\n /**\n * @notice Swaps an exact amount of ETH for as many output tokens as possible,\n * along the route determined by the path. The first element of path must be WBNB,\n * the last is the output token, and any intermediate elements represent\n * intermediate pairs to trade through (if, for example, a direct pair does not exist).\n * This method to swap deflationary tokens which would require supporting fee.\n * @dev amountIn is passed through the msg.value of the transaction\n * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n */\n function swapExactBNBForTokensAtSupportingFee(\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external payable virtual override nonReentrant ensure(deadline) ensurePath(path) returns (uint256 swapAmount) {\n address lastAsset = path[path.length - 1];\n uint256 balanceBefore = IERC20(lastAsset).balanceOf(to);\n _swapExactBNBForTokens(amountOutMin, path, to, TypesOfTokens.SUPPORTING_FEE);\n swapAmount = _checkForAmountOut(lastAsset, balanceBefore, amountOutMin, to);\n }\n\n /**\n * @notice Swaps an exact amount of input tokens for as many output ETH as possible,\n * along the route determined by the path. The first element of path is the input token,\n * the last is the output ETH, and any intermediate elements represent intermediate\n * pairs to trade through (if, for example, a direct pair does not exist).\n * @dev msg.sender should have already given the router an allowance of at least amountIn on the input token.\n * @param amountIn The address of the vToken contract to repay.\n * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n */\n function swapExactTokensForBNB(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) returns (uint256[] memory amounts) {\n amounts = _swapExactTokensForBNB(amountIn, amountOutMin, path, to, TypesOfTokens.NON_SUPPORTING_FEE);\n }\n\n /**\n * @notice Swaps an exact amount of input tokens for as many output ETH as possible,\n * along the route determined by the path. The first element of path is the input token,\n * the last is the output ETH, and any intermediate elements represent intermediate\n * pairs to trade through (if, for example, a direct pair does not exist).\n * This method to swap deflationary tokens which would require supporting fee.\n * @dev msg.sender should have already given the router an allowance of at least amountIn on the input token.\n * @param amountIn The address of the vToken contract to repay.\n * @param amountOutMin The minimum amount of output tokens that must be received for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n */\n function swapExactTokensForBNBAtSupportingFee(\n uint256 amountIn,\n uint256 amountOutMin,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external override nonReentrant ensure(deadline) ensurePath(path) returns (uint256 swapAmount) {\n uint256 balanceBefore = to.balance;\n _swapExactTokensForBNB(amountIn, amountOutMin, path, to, TypesOfTokens.SUPPORTING_FEE);\n uint256 balanceAfter = to.balance;\n swapAmount = balanceAfter - balanceBefore;\n if (swapAmount < amountOutMin) {\n revert SwapAmountLessThanAmountOutMin(swapAmount, amountOutMin);\n }\n }\n\n /**\n * @notice Swaps an as many amount of input tokens for as exact amount of tokens as output,\n * along the route determined by the path. The first element of path is the input token,\n * the last is the output token, and any intermediate elements represent intermediate\n * pairs to trade through (if, for example, a direct pair does not exist).\n * @dev msg.sender should have already given the router an allowance of at least amountIn on the input token.\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n **/\n function swapTokensForExactTokens(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external virtual override nonReentrant ensure(deadline) ensurePath(path) returns (uint256[] memory amounts) {\n amounts = _swapTokensForExactTokens(amountOut, amountInMax, path, to);\n }\n\n /**\n * @notice Swaps an as ETH as input tokens for as exact amount of tokens as output,\n * along the route determined by the path. The first element of path is the input WBNB,\n * the last is the output as token, and any intermediate elements represent intermediate\n * pairs to trade through (if, for example, a direct pair does not exist).\n * @dev msg.sender should have already given the router an allowance of at least amountIn on the input token.\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n **/\n function swapBNBForExactTokens(\n uint256 amountOut,\n address[] calldata path,\n address to,\n uint256 deadline\n )\n external\n payable\n virtual\n override\n nonReentrant\n ensure(deadline)\n ensurePath(path)\n returns (uint256[] memory amounts)\n {\n amounts = _swapBNBForExactTokens(amountOut, path, to);\n }\n\n /**\n * @notice Swaps an as many amount of input tokens for as exact amount of ETH as output,\n * along the route determined by the path. The first element of path is the input token,\n * the last is the output as ETH, and any intermediate elements represent intermediate\n * pairs to trade through (if, for example, a direct pair does not exist).\n * @dev msg.sender should have already given the router an allowance of at least amountIn on the input token.\n * @param amountOut The amount of the tokens needs to be as output token.\n * @param amountInMax The maximum amount of input tokens that can be taken for the transaction not to revert.\n * @param path Array with addresses of the underlying assets to be swapped\n * @param to Recipient of the output tokens.\n * @param deadline Unix timestamp after which the transaction will revert.\n **/\n function swapTokensForExactBNB(\n uint256 amountOut,\n uint256 amountInMax,\n address[] calldata path,\n address to,\n uint256 deadline\n ) external virtual override nonReentrant ensure(deadline) ensurePath(path) returns (uint256[] memory amounts) {\n amounts = _swapTokensForExactBNB(amountOut, amountInMax, path, to);\n }\n\n /**\n * @notice A public function to sweep accidental BEP-20 transfers to this contract. Tokens are sent to the address `to`, provided in input\n * @param token The address of the ERC-20 token to sweep\n * @param to Recipient of the output tokens.\n * @param sweepAmount The ampunt of the tokens to sweep\n * @custom:access Only Governance\n */\n function sweepToken(IERC20 token, address to, uint256 sweepAmount) external onlyOwner nonReentrant {\n if (to == address(0)) {\n revert ZeroAddress();\n }\n uint256 balance = token.balanceOf(address(this));\n if (sweepAmount > balance) {\n revert InsufficientBalance(sweepAmount, balance);\n }\n token.safeTransfer(to, sweepAmount);\n\n emit SweepToken(address(token), to, sweepAmount);\n }\n\n /**\n * @notice Supply token to a Venus market\n * @param path The addresses of the underlying token\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param swapAmount The amount of tokens supply to Venus Market.\n */\n function _supply(address path, address vTokenAddress, uint256 swapAmount) internal {\n TransferHelper.safeApprove(path, vTokenAddress, 0);\n TransferHelper.safeApprove(path, vTokenAddress, swapAmount);\n uint256 response = IVToken(vTokenAddress).mintBehalf(msg.sender, swapAmount);\n if (response != 0) {\n revert SupplyError(msg.sender, vTokenAddress, response);\n }\n }\n\n /**\n * @notice Repay a borrow from Venus market\n * @param path The addresses of the underlying token\n * @param vTokenAddress The address of the vToken contract for supplying assets.\n * @param swapAmount The amount of tokens repay to Venus Market.\n */\n function _repay(address path, address vTokenAddress, uint256 swapAmount) internal {\n TransferHelper.safeApprove(path, vTokenAddress, 0);\n TransferHelper.safeApprove(path, vTokenAddress, swapAmount);\n uint256 response = IVToken(vTokenAddress).repayBorrowBehalf(msg.sender, swapAmount);\n if (response != 0) {\n revert RepayError(msg.sender, vTokenAddress, response);\n }\n }\n\n /**\n * @notice Check if the balance of to minus the balanceBefore is greater or equal to the amountOutMin.\n * @param asset The address of the underlying token\n * @param balanceBefore Balance before the swap.\n * @param amountOutMin Min amount out threshold.\n * @param to Recipient of the output tokens.\n */\n function _checkForAmountOut(\n address asset,\n uint256 balanceBefore,\n uint256 amountOutMin,\n address to\n ) internal view returns (uint256 swapAmount) {\n uint256 balanceAfter = IERC20(asset).balanceOf(to);\n swapAmount = balanceAfter - balanceBefore;\n if (swapAmount < amountOutMin) {\n revert SwapAmountLessThanAmountOutMin(swapAmount, amountOutMin);\n }\n }\n\n /**\n * @notice Returns the difference between the balance of this and the balanceBefore\n * @param asset The address of the underlying token\n * @param balanceBefore Balance before the swap.\n */\n function _getSwapAmount(address asset, uint256 balanceBefore) internal view returns (uint256 swapAmount) {\n uint256 balanceAfter = IERC20(asset).balanceOf(address(this));\n swapAmount = balanceAfter - balanceBefore;\n }\n\n /**\n * @notice Check isVTokenListed and last address in the path should be vToken underlying.\n * @param vTokenAddress Address of the vToken.\n * @param underlying Address of the underlying asset.\n */\n function _ensureVTokenChecks(address vTokenAddress, address underlying) internal {\n _isVTokenListed(vTokenAddress);\n if (IVToken(vTokenAddress).underlying() != underlying) {\n revert VTokenUnderlyingInvalid(underlying);\n }\n }\n\n /**\n * @notice Check is vToken listed in the pool.\n * @param vToken Address of the vToken.\n */\n function _isVTokenListed(address vToken) internal view {\n bool isListed = InterfaceComptroller(comptrollerAddress).markets(vToken);\n if (!isListed) {\n revert VTokenNotListed(vToken);\n }\n }\n\n /**\n * @notice Mint vBNB tokens to the market then transfer them to user\n * @param swapAmount Swapped BNB amount\n */\n function _mintVBNBandTransfer(uint256 swapAmount) internal {\n uint256 vBNBBalanceBefore = IVBNB(vBNBAddress).balanceOf(address(this));\n IVBNB(vBNBAddress).mint{ value: swapAmount }();\n uint256 vBNBBalanceAfter = IVBNB(vBNBAddress).balanceOf(address(this));\n IERC20(vBNBAddress).safeTransfer(msg.sender, (vBNBBalanceAfter - vBNBBalanceBefore));\n }\n}\n" + }, + "contracts/test/AccessControlManagerMock.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\ncontract AccessControlManagerMock {\n address public owner;\n\n constructor(address _owner) {\n owner = _owner;\n }\n\n function isAllowedToCall(address account, string calldata functionSig) public view returns (bool) {\n if (account == owner) {\n return true;\n }\n\n functionSig;\n\n return false;\n }\n}\n" + }, + "contracts/test/BadFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./MockFlashLoanReceiver.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\n\ncontract BadFlashLoanReceiver is MockFlashLoanReceiver {\n constructor(ComptrollerInterface comptroller) MockFlashLoanReceiver(comptroller) {}\n\n function executeOperation(\n VToken[] calldata,\n uint256[] calldata,\n uint256[] calldata,\n address,\n address,\n bytes calldata\n ) external override returns (bool, uint256[] memory) {\n return (false, new uint256[](0));\n }\n}\n" + }, + "contracts/test/BorrowDebtFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./MockFlashLoanReceiver.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\n\ncontract BorrowDebtFlashLoanReceiver is MockFlashLoanReceiver {\n constructor(ComptrollerInterface comptroller) MockFlashLoanReceiver(comptroller) {}\n\n function executeOperation(\n VToken[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata,\n address initiator,\n address onBehalf,\n bytes calldata param\n ) external override returns (bool, uint256[] memory) {\n // 👇 Your custom logic for the flash loan should be implemented here 👇\n /** YOUR CUSTOM LOGIC HERE */\n initiator;\n onBehalf;\n param;\n // 👆 Your custom logic for the flash loan should be implemented above here 👆\n\n uint256[] memory approvedTokens = _approveRepaymentsBorrow(assets, amounts);\n return (true, approvedTokens);\n }\n\n function _approveRepaymentsBorrow(\n VToken[] calldata assets,\n uint256[] calldata amounts\n ) private returns (uint256[] memory) {\n uint256 len = assets.length;\n uint256[] memory approvedTokens = new uint256[](len);\n for (uint256 k = 0; k < len; ++k) {\n uint256 total = amounts[k]; // Intentionally not adding premiums to create debt position\n IERC20NonStandard(assets[k].underlying()).approve(address(assets[k]), total);\n\n approvedTokens[k] = total;\n }\n return approvedTokens;\n }\n}\n" + }, + "contracts/test/ComptrollerHarness.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"./ComptrollerMock.sol\";\nimport \"../Comptroller/Unitroller.sol\";\n\ncontract ComptrollerHarness is ComptrollerMock {\n address internal xvsAddress;\n address internal vXVSAddress;\n uint public blockNumber;\n\n constructor() ComptrollerMock() {}\n\n function setVenusSupplyState(address vToken, uint224 index, uint32 blockNumber_) public {\n venusSupplyState[vToken].index = index;\n venusSupplyState[vToken].block = blockNumber_;\n }\n\n function setVenusBorrowState(address vToken, uint224 index, uint32 blockNumber_) public {\n venusBorrowState[vToken].index = index;\n venusBorrowState[vToken].block = blockNumber_;\n }\n\n function setVenusAccrued(address user, uint userAccrued) public {\n venusAccrued[user] = userAccrued;\n }\n\n function setXVSAddress(address xvsAddress_) public {\n xvsAddress = xvsAddress_;\n }\n\n function setXVSVTokenAddress(address vXVSAddress_) public {\n vXVSAddress = vXVSAddress_;\n }\n\n /**\n * @notice Set the amount of XVS distributed per block\n * @param venusRate_ The amount of XVS wei per block to distribute\n */\n function harnessSetVenusRate(uint venusRate_) public {\n venusRate = venusRate_;\n }\n\n /**\n * @notice Recalculate and update XVS speeds for all XVS markets\n */\n function harnessRefreshVenusSpeeds() public {\n VToken[] memory allMarkets_ = allMarkets;\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusSupplyIndex(address(vToken));\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n }\n\n Exp memory totalUtility = Exp({ mantissa: 0 });\n Exp[] memory utilities = new Exp[](allMarkets_.length);\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n if (venusSpeeds[address(vToken)] > 0) {\n Exp memory assetPrice = Exp({ mantissa: oracle.getUnderlyingPrice(address(vToken)) });\n Exp memory utility = mul_(assetPrice, vToken.totalBorrows());\n utilities[i] = utility;\n totalUtility = add_(totalUtility, utility);\n }\n }\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets[i];\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(venusRate, div_(utilities[i], totalUtility)) : 0;\n setVenusSpeedInternal(vToken, newSpeed, newSpeed);\n }\n }\n\n function setVenusBorrowerIndex(address vToken, address borrower, uint index) public {\n venusBorrowerIndex[vToken][borrower] = index;\n }\n\n function setVenusSupplierIndex(address vToken, address supplier, uint index) public {\n venusSupplierIndex[vToken][supplier] = index;\n }\n\n function harnessDistributeAllBorrowerVenus(\n address vToken,\n address borrower,\n uint marketBorrowIndexMantissa\n ) public {\n distributeBorrowerVenus(vToken, borrower, Exp({ mantissa: marketBorrowIndexMantissa }));\n venusAccrued[borrower] = grantXVSInternal(borrower, venusAccrued[borrower], 0, false);\n }\n\n function harnessDistributeAllSupplierVenus(address vToken, address supplier) public {\n distributeSupplierVenus(vToken, supplier);\n venusAccrued[supplier] = grantXVSInternal(supplier, venusAccrued[supplier], 0, false);\n }\n\n function harnessUpdateVenusBorrowIndex(address vToken, uint marketBorrowIndexMantissa) public {\n updateVenusBorrowIndex(vToken, Exp({ mantissa: marketBorrowIndexMantissa }));\n }\n\n function harnessUpdateVenusSupplyIndex(address vToken) public {\n updateVenusSupplyIndex(vToken);\n }\n\n function harnessDistributeBorrowerVenus(address vToken, address borrower, uint marketBorrowIndexMantissa) public {\n distributeBorrowerVenus(vToken, borrower, Exp({ mantissa: marketBorrowIndexMantissa }));\n }\n\n function harnessDistributeSupplierVenus(address vToken, address supplier) public {\n distributeSupplierVenus(vToken, supplier);\n }\n\n function harnessTransferVenus(address user, uint userAccrued, uint threshold) public returns (uint) {\n if (userAccrued > 0 && userAccrued >= threshold) {\n return grantXVSInternal(user, userAccrued, 0, false);\n }\n return userAccrued;\n }\n\n function harnessAddVenusMarkets(address[] memory vTokens) public {\n for (uint i = 0; i < vTokens.length; i++) {\n // temporarily set venusSpeed to 1 (will be fixed by `harnessRefreshVenusSpeeds`)\n setVenusSpeedInternal(VToken(vTokens[i]), 1, 1);\n }\n }\n\n function harnessSetMintedVAIs(address user, uint amount) public {\n mintedVAIs[user] = amount;\n }\n\n function harnessFastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function getBlockNumber() internal view override returns (uint) {\n return blockNumber;\n }\n\n function getVenusMarkets() public view returns (address[] memory) {\n uint m = allMarkets.length;\n uint n = 0;\n for (uint i = 0; i < m; i++) {\n if (venusSpeeds[address(allMarkets[i])] > 0) {\n n++;\n }\n }\n\n address[] memory venusMarkets = new address[](n);\n uint k = 0;\n for (uint i = 0; i < m; i++) {\n if (venusSpeeds[address(allMarkets[i])] > 0) {\n venusMarkets[k++] = address(allMarkets[i]);\n }\n }\n return venusMarkets;\n }\n\n function harnessSetReleaseStartBlock(uint startBlock) external {\n releaseStartBlock = startBlock;\n }\n\n function harnessAddVtoken(address vToken) external {\n getCorePoolMarket(vToken).isListed = true;\n }\n}\n\ncontract EchoTypesComptroller is UnitrollerAdminStorage {\n function stringy(string memory s) public pure returns (string memory) {\n return s;\n }\n\n function addresses(address a) public pure returns (address) {\n return a;\n }\n\n function booly(bool b) public pure returns (bool) {\n return b;\n }\n\n function listOInts(uint[] memory u) public pure returns (uint[] memory) {\n return u;\n }\n\n function reverty() public pure {\n require(false, \"gotcha sucka\");\n }\n\n function becomeBrains(address payable unitroller) public {\n Unitroller(unitroller)._acceptImplementation();\n }\n}\n" + }, + "contracts/test/ComptrollerMock.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Comptroller/Diamond/facets/MarketFacet.sol\";\nimport \"../Comptroller/Diamond/facets/PolicyFacet.sol\";\nimport \"../Comptroller/Diamond/facets/RewardFacet.sol\";\nimport \"../Comptroller/Diamond/facets/SetterFacet.sol\";\nimport \"../Comptroller/Diamond/facets/FlashLoanFacet.sol\";\nimport \"../Comptroller/Unitroller.sol\";\n\n// This contract contains all methods of Comptroller implementation in different facets at one place for testing purpose\n// This contract does not have diamond functionality(i.e delegate call to facets methods)\ncontract ComptrollerMock is MarketFacet, PolicyFacet, RewardFacet, SetterFacet, FlashLoanFacet {\n constructor() {\n admin = msg.sender;\n }\n\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n function _setComptrollerLens(ComptrollerLensInterface comptrollerLens_) external override returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/test/ComptrollerMockR1.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Comptroller/legacy/Diamond/facets/MarketFacetR1.sol\";\nimport \"../Comptroller/legacy/Diamond/facets/PolicyFacetR1.sol\";\nimport \"../Comptroller/legacy/Diamond/facets/RewardFacetR1.sol\";\nimport \"../Comptroller/legacy/Diamond/facets/SetterFacetR1.sol\";\nimport \"../Comptroller/Unitroller.sol\";\n\n// This contract contains all methods of Comptroller implementation in different facets at one place for testing purpose\n// This contract does not have diamond functionality(i.e delegate call to facets methods)\ncontract ComptrollerMockR1 is MarketFacetR1, PolicyFacetR1, RewardFacetR1, SetterFacetR1 {\n constructor() {\n admin = msg.sender;\n }\n\n function _become(Unitroller unitroller) public {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can\");\n require(unitroller._acceptImplementation() == 0, \"not authorized\");\n }\n\n function _setComptrollerLens(ComptrollerLensInterfaceR1 comptrollerLens_) external override returns (uint) {\n ensureAdmin();\n ensureNonzeroAddress(address(comptrollerLens_));\n address oldComptrollerLens = address(comptrollerLens);\n comptrollerLens = comptrollerLens_;\n emit NewComptrollerLens(oldComptrollerLens, address(comptrollerLens));\n\n return uint(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/test/ComptrollerScenario.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"./ComptrollerMock.sol\";\n\ncontract ComptrollerScenario is ComptrollerMock {\n uint public blockNumber;\n address public xvsAddress;\n address public vaiAddress;\n\n constructor() ComptrollerMock() {}\n\n function setXVSAddress(address xvsAddress_) public {\n xvsAddress = xvsAddress_;\n }\n\n // function getXVSAddress() public view returns (address) {\n // return xvsAddress;\n // }\n\n function setVAIAddress(address vaiAddress_) public {\n vaiAddress = vaiAddress_;\n }\n\n function getVAIAddress() public view returns (address) {\n return vaiAddress;\n }\n\n function membershipLength(VToken vToken) public view returns (uint) {\n return accountAssets[address(vToken)].length;\n }\n\n function fastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n\n return blockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function getBlockNumber() internal view override returns (uint) {\n return blockNumber;\n }\n\n function getVenusMarkets() public view returns (address[] memory) {\n uint m = allMarkets.length;\n uint n = 0;\n for (uint i = 0; i < m; i++) {\n if (getCorePoolMarket(address(allMarkets[i])).isVenus) {\n n++;\n }\n }\n\n address[] memory venusMarkets = new address[](n);\n uint k = 0;\n for (uint i = 0; i < m; i++) {\n if (getCorePoolMarket(address(allMarkets[i])).isVenus) {\n venusMarkets[k++] = address(allMarkets[i]);\n }\n }\n return venusMarkets;\n }\n\n function unlist(VToken vToken) public {\n getCorePoolMarket(address(vToken)).isListed = false;\n }\n\n /**\n * @notice Recalculate and update XVS speeds for all XVS markets\n */\n function refreshVenusSpeeds() public {\n VToken[] memory allMarkets_ = allMarkets;\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n Exp memory borrowIndex = Exp({ mantissa: vToken.borrowIndex() });\n updateVenusSupplyIndex(address(vToken));\n updateVenusBorrowIndex(address(vToken), borrowIndex);\n }\n\n Exp memory totalUtility = Exp({ mantissa: 0 });\n Exp[] memory utilities = new Exp[](allMarkets_.length);\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets_[i];\n if (venusSpeeds[address(vToken)] > 0) {\n Exp memory assetPrice = Exp({ mantissa: oracle.getUnderlyingPrice(address(vToken)) });\n Exp memory utility = mul_(assetPrice, vToken.totalBorrows());\n utilities[i] = utility;\n totalUtility = add_(totalUtility, utility);\n }\n }\n\n for (uint i = 0; i < allMarkets_.length; i++) {\n VToken vToken = allMarkets[i];\n uint newSpeed = totalUtility.mantissa > 0 ? mul_(venusRate, div_(utilities[i], totalUtility)) : 0;\n setVenusSpeedInternal(vToken, newSpeed, newSpeed);\n }\n }\n}\n" + }, + "contracts/test/DiamondHarness.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Comptroller/Diamond/Diamond.sol\";\n\ncontract DiamondHarness is Diamond {\n function getFacetAddress(bytes4 sig) public view returns (address) {\n address facet = _selectorToFacetAndPosition[sig].facetAddress;\n require(facet != address(0), \"Diamond: Function does not exist\");\n return facet;\n }\n}\n" + }, + "contracts/test/DiamondHarnessInterface.sol": { + "content": "pragma solidity 0.8.25;\n\ninterface DiamondHarnessInterface {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition;\n }\n\n struct Facet {\n address facetAddress;\n bytes4[] functionSelectors;\n }\n\n function getFacetAddress(bytes4 sig) external view returns (address);\n\n function diamondCut(FacetCut[] calldata _diamondCut) external;\n\n function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory _facetFunctionSelectors);\n\n function facetPosition(address _facet) external view returns (uint256);\n\n function facetAddresses() external view returns (address[] memory facetAddresses_);\n\n function facets() external view returns (Facet[] memory facets);\n\n function facetAddress(bytes4 _functionSelector) external view returns (FacetAddressAndPosition memory);\n}\n" + }, + "contracts/test/EvilXDelegator.sol": { + "content": "pragma solidity 0.8.25;\n\nimport { InterestRateModelV8 } from \"../InterestRateModels/InterestRateModelV8.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VTokenInterface, VBep20Interface, VDelegatorInterface } from \"../Tokens/VTokens/VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20Delegator Contract\n * @notice VTokens which wrap an EIP-20 underlying and delegate to an implementation\n * @author Venus\n */\ncontract EvilXDelegator is VTokenInterface, VBep20Interface, VDelegatorInterface {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData The encoded args for becomeImplementation\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint256 initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(\n implementation_,\n abi.encodeWithSignature(\n \"initialize(address,address,address,uint256,string,string,uint8)\",\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n )\n );\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_, false, becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) public {\n require(msg.sender == admin, \"VBep20Delegator::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature(\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint256 mintAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"mint(uint256)\", mintAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mintBehalf(address receiver, uint256 mintAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"mintBehalf(address,uint256)\", receiver, mintAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint256 redeemTokens) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"redeem(uint256)\", redeemTokens));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint256 redeemAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"redeemUnderlying(uint256)\", redeemAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrow(uint256 borrowAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrow(uint256)\", borrowAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint256 repayAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"repayBorrow(uint256)\", repayAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint256 repayAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"repayBorrowBehalf(address,uint256)\", borrower, repayAmount)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function liquidateBorrow(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"liquidateBorrow(address,uint256,address)\", borrower, repayAmount, vTokenCollateral)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"transfer(address,uint256)\", dst, amount));\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"transferFrom(address,address,uint256)\", src, dst, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"approve(address,uint256)\", spender, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (-1 means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"allowance(address,address)\", owner, spender)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"balanceOf(address)\", owner));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"balanceOfUnderlying(address)\", owner));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view override returns (uint256, uint256, uint256, uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"getAccountSnapshot(address)\", account)\n );\n return abi.decode(data, (uint256, uint256, uint256, uint256));\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"borrowRatePerBlock()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"supplyRatePerBlock()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"totalBorrowsCurrent()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrowBalanceCurrent(address)\", account));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"borrowBalanceStored(address)\", account)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"exchangeRateCurrent()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() public view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"exchangeRateStored()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint256) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"getCash()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves.\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n function accrueInterest() public override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"accrueInterest()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function seize(address liquidator, address borrower, uint256 seizeTokens) external override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"seize(address,address,uint256)\", liquidator, borrower, seizeTokens)\n );\n return abi.decode(data, (uint256));\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setPendingAdmin(address)\", newPendingAdmin)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setComptroller(address)\", newComptroller)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setReserveFactor(uint256 newReserveFactorMantissa) external override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setReserveFactor(uint256)\", newReserveFactorMantissa)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_acceptAdmin()\"));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from admin\n * @param addAmount Amount of reserves to add\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint256 addAmount) external returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_addReserves(uint256)\", addAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _reduceReserves(uint256 reduceAmount) external override returns (uint256) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_reduceReserves(uint256)\", reduceAmount));\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Opens a debt position for the borrower as part of flash loan repayment\n * @dev This function is specifically called during flash loan operations when the repayment\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\n * and updates the borrower's balance. It also emits a Borrow event and calls the\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\n * if the market's block number is not current.\n * @param borrower The address of the borrower who will have the debt position created\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\n */\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"flashLoanDebtPosition(address,uint256)\", borrower, borrowAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public override returns (uint256) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setInterestRateModel(address)\", newInterestRateModel)\n );\n return abi.decode(data, (uint256));\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize())\n }\n }\n return returnData;\n }\n\n /**\n * @notice Delegates execution to the implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToImplementation(bytes memory data) public returns (bytes memory) {\n return delegateTo(implementation, data);\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n (bool success, bytes memory returnData) = address(this).staticcall(\n abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data)\n );\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize())\n }\n }\n return abi.decode(returnData, (bytes));\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n */\n fallback() external {\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/test/EvilXToken.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Tokens/VTokens/VBep20Immutable.sol\";\nimport \"../Tokens/VTokens/VBep20Delegator.sol\";\nimport \"../Tokens/VTokens/VBep20Delegate.sol\";\nimport \"./ComptrollerScenario.sol\";\nimport \"../Comptroller/ComptrollerInterface.sol\";\n\ncontract VBep20Scenario is VBep20Immutable {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\n// doTransferOut method of this token supposed to be compromised and contians malicious code which\n// can be used by attacker to compromise the protocol working.\ncontract EvilXToken is VBep20Delegate {\n event Log(string x, address y);\n event Log(string x, uint y);\n event LogLiquidity(uint liquidity);\n\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n address public comptrollerAddress;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function setComptrollerAddress(address _comptrollerAddress) external {\n comptrollerAddress = _comptrollerAddress;\n }\n\n function exchangeRateStoredInternal() internal view override returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function doTransferOut(address payable to, uint amount) internal override {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n super.doTransferOut(to, amount);\n\n // Checking the Liquidity of the user after the tranfer.\n // solhint-disable-next-line no-unused-vars\n (uint errorCode, uint liquidity, uint shortfall) = ComptrollerInterface(comptrollerAddress).getAccountLiquidity(\n msg.sender\n );\n emit LogLiquidity(liquidity);\n return;\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessIncrementTotalBorrows(uint addtlBorrow_) public {\n totalBorrows = totalBorrows + addtlBorrow_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount, true);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModelV8(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n\n function harnessSetInternalCash(uint256 _internalCash) public {\n internalCash = _internalCash;\n }\n}\n" + }, + "contracts/test/FlashLoanReceiverBase.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { IFlashLoanReceiver } from \"../FlashLoan/interfaces/IFlashLoanReceiver.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\n\n/// @title FlashLoanReceiverBase\n/// @notice A base contract for implementing flashLoan receiver logic.\n/// @dev This abstract contract provides the necessary structure for inheriting contracts to implement the `IFlashLoanReceiver` interface.\n/// It stores a reference to the Comptroller contract, which manages various aspects of the protocol.\nabstract contract FlashLoanReceiverBase is IFlashLoanReceiver {\n /// @notice The Comptroller contract that governs the protocol.\n /// @dev This variable stores the address of the Comptroller contract, which cannot be changed after deployment.\n ComptrollerInterface public COMPTROLLER;\n\n /**\n * @notice Constructor to initialize the base contract with the Comptroller address.\n * @param comptroller_ The address of the Comptroller contract that oversees the protocol.\n */\n constructor(ComptrollerInterface comptroller_) {\n COMPTROLLER = comptroller_;\n }\n}\n" + }, + "contracts/test/imports.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n// Force Hardhat to compile DeviationBoundedOracle from node_modules so that\n// @openzeppelin/hardhat-upgrades can run storage-layout validation.\nimport { DeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/DeviationBoundedOracle.sol\";\n" + }, + "contracts/test/InsufficientRepaymentFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport \"./MockFlashLoanReceiver.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\n\ncontract InsufficientRepaymentFlashLoanReceiver is MockFlashLoanReceiver {\n constructor(ComptrollerInterface comptroller) MockFlashLoanReceiver(comptroller) {}\n\n function executeOperation(\n VToken[] calldata assets,\n uint256[] calldata,\n uint256[] calldata premiums,\n address initiator,\n address onBehalf,\n bytes calldata param\n ) external override returns (bool, uint256[] memory) {\n initiator;\n onBehalf;\n param;\n\n uint256[] memory approvedTokens = _approveInsufficientRepayments(assets, premiums);\n return (true, approvedTokens);\n }\n\n function _approveInsufficientRepayments(\n VToken[] calldata assets,\n uint256[] calldata premiums\n ) private returns (uint256[] memory) {\n uint256 len = assets.length;\n uint256[] memory approvedTokens = new uint256[](len);\n\n for (uint256 k = 0; k < len; ++k) {\n // Approve only half of the premium (fee) - intentionally insufficient\n uint256 insufficientAmount = premiums[k] / 2;\n IERC20NonStandard(assets[k].underlying()).approve(address(assets[k]), insufficientAmount);\n\n approvedTokens[k] = insufficientAmount;\n }\n return approvedTokens;\n }\n}\n" + }, + "contracts/test/LiquidatorHarness.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../Liquidator/Liquidator.sol\";\nimport \"@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol\";\n\ncontract LiquidatorHarness is Liquidator {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address comptroller_, address payable vBnb_, address wBnb_) Liquidator(comptroller_, vBnb_, wBnb_) {}\n\n function initialize(\n uint256 liquidationIncentiveMantissa_,\n address accessControlManager_,\n address protocolShareReserve_\n ) external override initializer {\n __Liquidator_init(liquidationIncentiveMantissa_, accessControlManager_, protocolShareReserve_);\n }\n\n event DistributeLiquidationIncentive(uint256 seizeTokensForTreasury, uint256 seizeTokensForLiquidator);\n\n /// @dev Splits the received vTokens between the liquidator and treasury.\n function distributeLiquidationIncentive(\n address borrower,\n IVToken vTokenCollateral,\n uint256 siezedAmount\n ) public returns (uint256 ours, uint256 theirs) {\n (ours, theirs) = super._distributeLiquidationIncentive(borrower, vTokenCollateral, siezedAmount);\n emit DistributeLiquidationIncentive(ours, theirs);\n return (ours, theirs);\n }\n\n /// @dev Computes the amounts that would go to treasury and to the liquidator.\n function splitLiquidationIncentive(\n address borrower,\n address vTokenCollateral,\n uint256 seizedAmount\n ) public view returns (uint256 ours, uint256 theirs) {\n return super._splitLiquidationIncentive(borrower, vTokenCollateral, seizedAmount);\n }\n}\n" + }, + "contracts/test/MockFlashLoanReceiver.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { FlashLoanReceiverBase } from \"./FlashLoanReceiverBase.sol\";\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { IERC20NonStandard } from \"../Tokens/test/IERC20NonStandard.sol\";\n\n/// @title MockFlashLoanReceiver\n/// @notice A mock implementation of a flashLoan receiver contract that interacts with the Comptroller to request and handle flash loans.\n/// @dev This contract extends `FlashLoanReceiverBase` and implements custom logic to request flash loans and repay them.\ncontract MockFlashLoanReceiver is FlashLoanReceiverBase {\n /**\n * @notice Constructor to initialize the flashLoan receiver with the Comptroller contract.\n * @param comptroller The address of the Comptroller contract used to request flash loans.\n */\n constructor(ComptrollerInterface comptroller) FlashLoanReceiverBase(comptroller) {}\n\n /**\n * @notice Requests a flash loan from the Comptroller contract.\n * @dev This function calls the `executeFlashLoan` function from the Comptroller to initiate a flash loan.\n * @param assets An array of VToken contracts that support flash loans.\n * @param amounts An array of amounts to borrow in the flash loan for each corresponding asset.\n * @param receiver The address of the contract that will receive the flashLoan and execute the operation.\n * @param param Additional encoded parameters passed with the flash loan.\n */\n function requestFlashLoan(\n VToken[] calldata assets,\n uint256[] calldata amounts,\n address payable receiver,\n bytes calldata param\n ) external {\n // Request the flashLoan from the Comptroller contract\n COMPTROLLER.executeFlashLoan(payable(msg.sender), receiver, assets, amounts, param);\n }\n\n /**\n * @notice Executes custom logic after receiving the flash loan.\n * @dev This function is called by the Comptroller contract as part of the flashLoan process.\n * It must repay the loan amount plus the premium for each borrowed asset.\n * @param assets The VToken contracts for the flash-borrowed assets.\n * @param amounts The amounts of each asset borrowed.\n * @param premiums The fees for each flash-borrowed asset.\n * @param initiator The address that initiated the flash loan.\n * @param onBehalf The address of the user whose debt position will be used for the flashLoan.\n * @param param Additional encoded parameters passed with the flash loan.\n * @return True if the operation succeeds and the debt plus premium is repaid, false otherwise.\n */\n function executeOperation(\n VToken[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata premiums,\n address initiator,\n address onBehalf,\n bytes calldata param\n ) external virtual returns (bool, uint256[] memory) {\n // 👇 Your custom logic for the flash loan should be implemented here 👇\n /** YOUR CUSTOM LOGIC HERE */\n initiator;\n onBehalf;\n param;\n // 👆 Your custom logic for the flash loan should be implemented above here 👆\n\n uint256[] memory approvedTokens = _approveRepayments(assets, amounts, premiums);\n return (true, approvedTokens);\n }\n\n function _approveRepayments(\n VToken[] calldata assets,\n uint256[] calldata amounts,\n uint256[] calldata premiums\n ) private returns (uint256[] memory) {\n uint256 len = assets.length;\n uint256[] memory approvedTokens = new uint256[](len);\n for (uint256 k = 0; k < len; ++k) {\n uint256 total = amounts[k] + premiums[k];\n IERC20NonStandard(assets[k].underlying()).approve(address(assets[k]), total);\n approvedTokens[k] = total;\n }\n return approvedTokens;\n }\n}\n" + }, + "contracts/test/MockProtocolShareReserve.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\n\ninterface IIncomeDestination {\n function updateAssetsState(address comptroller, address asset) external;\n}\n\ninterface IVToken {\n function underlying() external view returns (address);\n}\n\ninterface IPrime is IIncomeDestination {\n function accrueInterest(address vToken) external;\n\n function vTokenForAsset(address asset) external view returns (address);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n\ninterface IPoolRegistry {\n /// @notice Get VToken in the Pool for an Asset\n function getVTokenForAsset(address comptroller, address asset) external view returns (address);\n\n /// @notice Get the addresss of the Pools supported that include a market for the provided asset\n function getPoolsSupportedByAsset(address asset) external view returns (address[] memory);\n}\n\ninterface IMockProtocolShareReserve {\n /// @notice it represents the type of vToken income\n enum IncomeType {\n SPREAD,\n LIQUIDATION,\n FLASHLOAN\n }\n\n function updateAssetsState(address comptroller, address asset, IncomeType incomeType) external;\n}\n\ninterface IComptroller {\n function isComptroller() external view returns (bool);\n\n function markets(address) external view returns (bool);\n\n function getAllMarkets() external view returns (address[] memory);\n}\n\nerror InvalidAddress();\nerror UnsupportedAsset();\nerror InvalidTotalPercentage();\nerror InvalidMaxLoopsLimit();\n\n/**\n * @title MaxLoopsLimitHelper\n * @author Venus\n * @notice Abstract contract used to avoid collection with too many items that would generate gas errors and DoS.\n */\nabstract contract MaxLoopsLimitHelper {\n // Limit for the loops to avoid the DOS\n uint256 public maxLoopsLimit;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n\n /// @notice Emitted when max loops limit is set\n event MaxLoopsLimitUpdated(uint256 oldMaxLoopsLimit, uint256 newmaxLoopsLimit);\n\n /// @notice Thrown an error on maxLoopsLimit exceeds for any loop\n error MaxLoopsLimitExceeded(uint256 loopsLimit, uint256 requiredLoops);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param limit Limit for the max loops can execute at a time\n */\n function _setMaxLoopsLimit(uint256 limit) internal {\n require(limit > maxLoopsLimit, \"Comptroller: Invalid maxLoopsLimit\");\n\n uint256 oldMaxLoopsLimit = maxLoopsLimit;\n maxLoopsLimit = limit;\n\n emit MaxLoopsLimitUpdated(oldMaxLoopsLimit, limit);\n }\n\n /**\n * @notice Compare the maxLoopsLimit with number of the times loop iterate\n * @param len Length of the loops iterate\n * @custom:error MaxLoopsLimitExceeded error is thrown when loops length exceeds maxLoopsLimit\n */\n function _ensureMaxLoops(uint256 len) internal view {\n if (len > maxLoopsLimit) {\n revert MaxLoopsLimitExceeded(maxLoopsLimit, len);\n }\n }\n}\n\ncontract MockProtocolShareReserve is\n AccessControlledV8,\n ReentrancyGuardUpgradeable,\n MaxLoopsLimitHelper,\n IMockProtocolShareReserve\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice protocol income is categorized into two schemas.\n /// The first schema is the default one\n /// The second schema is for spread income from prime markets in core protocol\n enum Schema {\n DEFAULT,\n SPREAD_PRIME_CORE\n }\n\n struct DistributionConfig {\n Schema schema;\n /// @dev percenatge is represented without any scale\n uint256 percentage;\n address destination;\n }\n\n /// @notice address of core pool comptroller contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable CORE_POOL_COMPTROLLER;\n\n /// @notice address of WBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WBNB;\n\n /// @notice address of vBNB contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable vBNB;\n\n /// @notice address of Prime contract\n address public prime;\n\n /// @notice address of pool registry contract\n address public poolRegistry;\n\n uint256 private constant MAX_PERCENT = 100;\n\n /// @notice comptroller => asset => schema => balance\n mapping(address => mapping(address => mapping(Schema => uint256))) public assetsReserves;\n\n /// @notice asset => balance\n mapping(address => uint256) public totalAssetReserve;\n\n /// @notice configuration for different income distribution targets\n DistributionConfig[] public distributionTargets;\n\n /// @notice Emitted when pool registry address is updated\n event PoolRegistryUpdated(address indexed oldPoolRegistry, address indexed newPoolRegistry);\n\n /// @notice Emitted when prime address is updated\n event PrimeUpdated(address indexed oldPrime, address indexed newPrime);\n\n /// @notice Event emitted after the updation of the assets reserves.\n event AssetsReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n uint256 amount,\n IncomeType incomeType,\n Schema schema\n );\n\n /// @notice Event emitted when an asset is released to a target\n event AssetReleased(\n address indexed destination,\n address indexed asset,\n Schema schema,\n uint256 percent,\n uint256 amount\n );\n\n /// @notice Event emitted when asset reserves state is updated\n event ReservesUpdated(\n address indexed comptroller,\n address indexed asset,\n Schema schema,\n uint256 oldBalance,\n uint256 newBalance\n );\n\n /// @notice Event emitted when distribution configuration is updated\n event DistributionConfigUpdated(\n address indexed destination,\n uint256 oldPercentage,\n uint256 newPercentage,\n Schema schema\n );\n\n /// @notice Event emitted when distribution configuration is added\n event DistributionConfigAdded(address indexed destination, uint256 percentage, Schema schema);\n\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(address _corePoolComptroller, address _wbnb, address _vbnb) {\n if (_corePoolComptroller == address(0)) revert InvalidAddress();\n if (_wbnb == address(0)) revert InvalidAddress();\n if (_vbnb == address(0)) revert InvalidAddress();\n\n CORE_POOL_COMPTROLLER = _corePoolComptroller;\n WBNB = _wbnb;\n vBNB = _vbnb;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @dev Initializes the deployer to owner.\n * @param _accessControlManager The address of ACM contract\n * @param _loopsLimit Limit for the loops in the contract to avoid DOS\n */\n function initialize(address _accessControlManager, uint256 _loopsLimit) external initializer {\n __AccessControlled_init(_accessControlManager);\n __ReentrancyGuard_init();\n _setMaxLoopsLimit(_loopsLimit);\n }\n\n /**\n * @dev Pool registry setter.\n * @param _poolRegistry Address of the pool registry\n * @custom:error ZeroAddressNotAllowed is thrown when pool registry address is zero\n */\n function setPoolRegistry(address _poolRegistry) external onlyOwner {\n if (_poolRegistry == address(0)) revert InvalidAddress();\n emit PoolRegistryUpdated(poolRegistry, _poolRegistry);\n poolRegistry = _poolRegistry;\n }\n\n /**\n * @dev Prime contract address setter.\n * @param _prime Address of the prime contract\n */\n function setPrime(address _prime) external onlyOwner {\n if (_prime == address(0)) revert InvalidAddress();\n emit PrimeUpdated(prime, _prime);\n prime = _prime;\n }\n\n /**\n * @dev Add or update destination targets based on destination address\n * @param configs configurations of the destinations.\n */\n function addOrUpdateDistributionConfigs(DistributionConfig[] memory configs) external nonReentrant {\n _checkAccessAllowed(\"addOrUpdateDistributionConfigs(DistributionConfig[])\");\n\n //we need to accrue and release funds to prime before updating the distribution configuration\n //because prime relies on getUnreleasedFunds and its return value may change after config update\n _accrueAndReleaseFundsToPrime();\n for (uint256 i; i < configs.length; ) {\n DistributionConfig memory _config = configs[i];\n require(_config.destination != address(0), \"ProtocolShareReserve: Destination address invalid\");\n\n bool updated = false;\n for (uint256 j = 0; j < distributionTargets.length; ) {\n DistributionConfig storage config = distributionTargets[j];\n\n if (_config.schema == config.schema && config.destination == _config.destination) {\n emit DistributionConfigUpdated(\n _config.destination,\n config.percentage,\n _config.percentage,\n _config.schema\n );\n config.percentage = _config.percentage;\n updated = true;\n break;\n }\n\n unchecked {\n ++j;\n }\n }\n\n if (!updated) {\n distributionTargets.push(_config);\n emit DistributionConfigAdded(_config.destination, _config.percentage, _config.schema);\n }\n\n unchecked {\n ++i;\n }\n }\n\n _ensurePercentages();\n _ensureMaxLoops(distributionTargets.length);\n }\n\n /**\n * @dev Release funds\n * @param comptroller the comptroller address of the pool\n * @param assets assets to be released to distribution targets\n */\n function releaseFunds(address comptroller, address[] memory assets) external nonReentrant {\n _accruePrimeInterest();\n\n for (uint256 i; i < assets.length; ) {\n _releaseFund(comptroller, assets[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Used to find out the amount of funds that's going to be released when release funds is called.\n * @param comptroller the comptroller address of the pool\n * @param schema the schema of the distribution target\n * @param destination the destination address of the distribution target\n * @param asset the asset address which will be released\n */\n function getUnreleasedFunds(\n address comptroller,\n Schema schema,\n address destination,\n address asset\n ) external view returns (uint256) {\n for (uint256 i; i < distributionTargets.length; ) {\n DistributionConfig storage _config = distributionTargets[i];\n if (_config.schema == schema && _config.destination == destination) {\n uint256 total = assetsReserves[comptroller][asset][schema];\n return (total * _config.percentage) / MAX_PERCENT;\n }\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Returns the total number of distribution targets\n */\n function totalDistributions() external view returns (uint256) {\n return distributionTargets.length;\n }\n\n /**\n * @dev Update the reserve of the asset for the specific pool after transferring to the protocol share reserve.\n * @param comptroller Comptroller address (pool)\n * @param asset Asset address.\n * @param incomeType type of income\n */\n function updateAssetsState(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) public override(IMockProtocolShareReserve) nonReentrant {\n if (!IComptroller(comptroller).isComptroller()) revert InvalidAddress();\n if (asset == address(0)) revert InvalidAddress();\n if (\n comptroller != CORE_POOL_COMPTROLLER &&\n IPoolRegistry(poolRegistry).getVTokenForAsset(comptroller, asset) == address(0)\n ) revert InvalidAddress();\n\n Schema schema = getSchema(comptroller, asset, incomeType);\n uint256 currentBalance = IERC20Upgradeable(asset).balanceOf(address(this));\n uint256 assetReserve = totalAssetReserve[asset];\n\n if (currentBalance > assetReserve) {\n uint256 balanceDifference;\n unchecked {\n balanceDifference = currentBalance - assetReserve;\n }\n\n assetsReserves[comptroller][asset][schema] += balanceDifference;\n totalAssetReserve[asset] += balanceDifference;\n emit AssetsReservesUpdated(comptroller, asset, balanceDifference, incomeType, schema);\n }\n }\n\n /**\n * @dev Fetches the list of prime markets and then accrues interest and\n * releases the funds to prime for each market\n */\n function _accrueAndReleaseFundsToPrime() internal {\n address[] memory markets = IPrime(prime).getAllMarkets();\n for (uint256 i; i < markets.length; ) {\n address market = markets[i];\n IPrime(prime).accrueInterest(market);\n _releaseFund(CORE_POOL_COMPTROLLER, _getUnderlying(market));\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev Fetches the list of prime markets and then accrues interest\n * to prime for each market\n */\n function _accruePrimeInterest() internal {\n // address[] memory markets = IPrime(prime).getAllMarkets();\n address[] memory markets = IPrime(prime).getAllMarkets();\n\n for (uint256 i; i < markets.length; ) {\n address market = markets[i];\n IPrime(prime).accrueInterest(market);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @dev asset from a particular pool to be release to distribution targets\n * @param comptroller Comptroller address(pool)\n * @param asset Asset address.\n */\n function _releaseFund(address comptroller, address asset) internal {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint256[] memory schemaBalances = new uint256[](totalSchemas);\n uint256 totalBalance;\n for (uint256 schemaValue; schemaValue < totalSchemas; ) {\n schemaBalances[schemaValue] = assetsReserves[comptroller][asset][Schema(schemaValue)];\n totalBalance += schemaBalances[schemaValue];\n\n unchecked {\n ++schemaValue;\n }\n }\n\n if (totalBalance == 0) {\n return;\n }\n\n uint256[] memory totalTransferAmounts = new uint256[](totalSchemas);\n for (uint256 i; i < distributionTargets.length; ) {\n DistributionConfig memory _config = distributionTargets[i];\n\n uint256 transferAmount = (schemaBalances[uint256(_config.schema)] * _config.percentage) / MAX_PERCENT;\n totalTransferAmounts[uint256(_config.schema)] += transferAmount;\n\n IERC20Upgradeable(asset).safeTransfer(_config.destination, transferAmount);\n IIncomeDestination(_config.destination).updateAssetsState(comptroller, asset);\n\n emit AssetReleased(_config.destination, asset, _config.schema, _config.percentage, transferAmount);\n\n unchecked {\n ++i;\n }\n }\n\n uint256[] memory newSchemaBalances = new uint256[](totalSchemas);\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n newSchemaBalances[schemaValue] = schemaBalances[schemaValue] - totalTransferAmounts[schemaValue];\n assetsReserves[comptroller][asset][Schema(schemaValue)] = newSchemaBalances[schemaValue];\n totalAssetReserve[asset] = totalAssetReserve[asset] - totalTransferAmounts[schemaValue];\n\n emit ReservesUpdated(\n comptroller,\n asset,\n Schema(schemaValue),\n schemaBalances[schemaValue],\n newSchemaBalances[schemaValue]\n );\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the schema based on comptroller, asset and income type\n * @param comptroller Comptroller address(pool)\n * @param asset Asset address.\n * @param incomeType type of income\n * @return schema schema for distribution\n */\n function getSchema(\n address comptroller,\n address asset,\n IncomeType incomeType\n ) internal view returns (Schema schema) {\n schema = Schema.DEFAULT;\n address vToken = IPrime(prime).vTokenForAsset(asset);\n if (vToken != address(0) && comptroller == CORE_POOL_COMPTROLLER && incomeType == IncomeType.SPREAD) {\n schema = Schema.SPREAD_PRIME_CORE;\n }\n }\n\n function _ensurePercentages() internal view {\n uint256 totalSchemas = uint256(type(Schema).max) + 1;\n uint256[] memory totalPercentages = new uint256[](totalSchemas);\n\n for (uint256 i; i < distributionTargets.length; ) {\n DistributionConfig memory config = distributionTargets[i];\n totalPercentages[uint256(config.schema)] += config.percentage;\n\n unchecked {\n ++i;\n }\n }\n for (uint256 schemaValue = 0; schemaValue < totalSchemas; ) {\n if (totalPercentages[schemaValue] != MAX_PERCENT && totalPercentages[schemaValue] != 0)\n revert InvalidTotalPercentage();\n\n unchecked {\n ++schemaValue;\n }\n }\n }\n\n /**\n * @dev Returns the underlying asset address for the vToken\n * @param vToken vToken address\n * @return asset address of asset\n */\n function _getUnderlying(address vToken) internal view returns (address) {\n if (vToken == vBNB) {\n return WBNB;\n } else {\n return IVToken(vToken).underlying();\n }\n }\n}\n" + }, + "contracts/test/MockToken.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport { ERC20 } from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract MockToken is ERC20 {\n uint8 private immutable _decimals;\n\n constructor(string memory name_, string memory symbol_, uint8 decimals_) ERC20(name_, symbol_) {\n _decimals = decimals_;\n }\n\n function faucet(uint256 amount) external {\n _mint(msg.sender, amount);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n}\n" + }, + "contracts/test/MockVBNB.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Tokens/VTokens/VToken.sol\";\n\n/**\n * @title Venus's vBNB Contract\n * @notice vToken which wraps BNB\n * @author Venus\n */\ncontract MockVBNB is VToken {\n /**\n * @notice Construct a new vBNB money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n */\n constructor(\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Send BNB to VBNB to mint\n */\n receive() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Reverts upon any failure\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits Mint event\n function mint() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @dev Reverts upon any failure\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrow() external payable {\n (uint err, ) = repayBorrowInternal(msg.value);\n requireNoError(err, \"repayBorrow failed\");\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @dev Reverts upon any failure\n * @param borrower The account with the debt being payed off\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrowBehalf(address borrower) external payable {\n (uint err, ) = repayBorrowBehalfInternal(borrower, msg.value);\n requireNoError(err, \"repayBorrowBehalf failed\");\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @dev Reverts upon any failure\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n */\n // @custom:event Emit LiquidateBorrow event on success\n function liquidateBorrow(address borrower, VToken vTokenCollateral) external payable {\n (uint err, ) = liquidateBorrowInternal(borrower, msg.value, vTokenCollateral);\n requireNoError(err, \"liquidateBorrow failed\");\n }\n\n function setTotalReserves(uint totalReserves_) external payable {\n totalReserves = totalReserves_;\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Perform the actual transfer in, which is a no-op\n * @param from Address sending the BNB\n * @param amount Amount of BNB being sent\n * @return The actual amount of BNB transferred\n */\n function doTransferIn(address from, uint amount) internal override returns (uint) {\n // Sanity checks\n require(msg.sender == from, \"sender mismatch\");\n require(msg.value == amount, \"value mismatch\");\n return amount;\n }\n\n function doTransferOut(address payable to, uint amount) internal override {\n /* Send the BNB, with minimal gas and revert on failure */\n to.transfer(amount);\n }\n\n /**\n * @notice Gets balance of this contract in terms of BNB, before this message\n * @dev This excludes the value of the current message, if any\n * @return The quantity of BNB owned by this contract\n */\n function getCashPrior() internal view override returns (uint) {\n (MathError err, uint startingBalance) = subUInt(address(this).balance, msg.value);\n require(err == MathError.NO_ERROR, \"cash prior math error\");\n return startingBalance;\n }\n\n function requireNoError(uint errCode, string memory message) internal pure {\n if (errCode == uint(Error.NO_ERROR)) {\n return;\n }\n\n bytes memory fullMessage = new bytes(bytes(message).length + 5);\n uint i;\n\n for (i = 0; i < bytes(message).length; i++) {\n fullMessage[i] = bytes(message)[i];\n }\n\n fullMessage[i + 0] = bytes1(uint8(32));\n fullMessage[i + 1] = bytes1(uint8(40));\n fullMessage[i + 2] = bytes1(uint8(48 + (errCode / 10)));\n fullMessage[i + 3] = bytes1(uint8(48 + (errCode % 10)));\n fullMessage[i + 4] = bytes1(uint8(41));\n\n require(errCode == uint(Error.NO_ERROR), string(fullMessage));\n }\n\n /**\n * @dev Function to simply retrieve block number\n * This exists mainly for inheriting test contracts to stub this result.\n */\n function getBlockNumber() internal view returns (uint) {\n return block.number;\n }\n\n /**\n * @notice Reduces reserves by transferring to admin\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReservesFresh(uint reduceAmount) internal override returns (uint) {\n // totalReserves - reduceAmount\n uint totalReservesNew;\n\n // Check caller is admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.REDUCE_RESERVES_ADMIN_CHECK);\n }\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != getBlockNumber()) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (getCashPrior() < reduceAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n totalReservesNew = totalReserves - reduceAmount;\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReservesNew;\n\n // // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n doTransferOut(admin, reduceAmount);\n\n emit ReservesReduced(admin, reduceAmount, totalReservesNew);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesReduced event\n function _reduceReserves(uint reduceAmount) external override nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\n return _reduceReservesFresh(reduceAmount);\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n // @custom:event Emits AccrueInterest event\n function accrueInterest() public override returns (uint) {\n /* Remember the initial block number */\n uint currentBlockNumber = getBlockNumber();\n uint accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return uint(Error.NO_ERROR);\n }\n\n /* Read the previous values out of storage */\n uint cashPrior = getCashPrior();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\n uint borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n require(borrowRateMantissa <= borrowRateMaxMantissa, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n require(mathErr == MathError.NO_ERROR, \"could not calculate block delta\");\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor;\n uint interestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return uint(Error.NO_ERROR);\n }\n}\n" + }, + "contracts/test/PrimeScenario.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport \"../Tokens/Prime/Prime.sol\";\n\ncontract PrimeScenario is Prime {\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wbnb,\n address _vbnb,\n uint256 _blocksPerYear,\n uint256 _stakingPeriod,\n uint256 _minimumStakedXVS,\n uint256 _maximumXVSCap,\n bool _timeBased\n ) Prime(_wbnb, _vbnb, _blocksPerYear, _stakingPeriod, _minimumStakedXVS, _maximumXVSCap, _timeBased) {}\n\n function calculateScore(uint256 xvs, uint256 capital) external view returns (uint256) {\n return Scores._calculateScore(xvs, capital, alphaNumerator, alphaDenominator);\n }\n\n function setPLP(address plp) external {\n primeLiquidityProvider = plp;\n }\n\n function mintForUser(address user) external {\n tokens[user] = Token(true, true);\n }\n\n function burnForUser(address user) external {\n tokens[user] = Token(false, false);\n }\n}\n" + }, + "contracts/test/SimplePriceOracle.sol": { + "content": "pragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport \"../Tokens/VTokens/VBep20.sol\";\n\ncontract SimplePriceOracle is ResilientOracleInterface {\n mapping(address => uint) internal prices;\n event PricePosted(address asset, uint previousPriceMantissa, uint requestedPriceMantissa, uint newPriceMantissa);\n\n function getUnderlyingPrice(address vToken) public view returns (uint) {\n string memory symbol = VToken(vToken).symbol();\n if (compareStrings(symbol, \"vBNB\")) {\n return 1e18;\n } else if (compareStrings(symbol, \"VAI\")) {\n return prices[address(vToken)];\n } else {\n return prices[address(VBep20(address(vToken)).underlying())];\n }\n }\n\n function getPrice(address asset) external view returns (uint256) {\n return prices[asset];\n }\n\n function updatePrice(address vToken) external {}\n\n function updateAssetPrice(address asset) external {}\n\n function setUnderlyingPrice(VToken vToken, uint underlyingPriceMantissa) public {\n address asset = address(VBep20(address(vToken)).underlying());\n emit PricePosted(asset, prices[asset], underlyingPriceMantissa, underlyingPriceMantissa);\n prices[asset] = underlyingPriceMantissa;\n }\n\n function setDirectPrice(address asset, uint price) public {\n emit PricePosted(asset, prices[asset], price, price);\n prices[asset] = price;\n }\n\n // v1 price oracle interface for use as backing of proxy\n function assetPrices(address asset) external view returns (uint) {\n return prices[asset];\n }\n\n function compareStrings(string memory a, string memory b) internal pure returns (bool) {\n return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));\n }\n}\n" + }, + "contracts/test/VAIControllerHarness.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Tokens/VAI/VAIController.sol\";\n\ncontract VAIControllerHarness is VAIController {\n uint public blockNumber;\n uint public blocksPerYear;\n\n constructor() VAIController() {\n admin = msg.sender;\n }\n\n function setVenusVAIState(uint224 index, uint32 blockNumber_) public {\n venusVAIState.index = index;\n venusVAIState.block = blockNumber_;\n }\n\n function setVAIAddress(address vaiAddress_) public {\n vai = vaiAddress_;\n }\n\n function getVAIAddress() public view override returns (address) {\n return vai;\n }\n\n function harnessRepayVAIFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayVAIFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateVAIFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateVAIFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessFastForward(uint blocks) public returns (uint) {\n blockNumber += blocks;\n return blockNumber;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function setBlockNumber(uint number) public {\n blockNumber = number;\n }\n\n function setBlocksPerYear(uint number) public {\n blocksPerYear = number;\n }\n\n function getBlockNumber() internal view override returns (uint) {\n return blockNumber;\n }\n\n function getBlocksPerYear() public view override returns (uint) {\n return blocksPerYear;\n }\n}\n" + }, + "contracts/test/VBep20Harness.sol": { + "content": "pragma solidity 0.8.25;\n\nimport \"../Tokens/VTokens/VBep20Immutable.sol\";\nimport \"../Tokens/VTokens/VBep20Delegator.sol\";\nimport \"../Tokens/VTokens/VBep20Delegate.sol\";\nimport \"./ComptrollerScenario.sol\";\n\ncontract VBep20Harness is VBep20Immutable {\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function doTransferOut(address payable to, uint amount) internal override {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n return super.doTransferOut(to, amount);\n }\n\n function exchangeRateStoredInternal() internal view override returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount, true);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModelV8(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n\n function harnessSetInternalCash(uint256 _internalCash) public {\n internalCash = _internalCash;\n }\n}\n\ncontract VBep20Scenario is VBep20Immutable {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n VBep20Immutable(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\ncontract VEvil is VBep20Scenario {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n )\n VBep20Scenario(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_\n )\n {}\n\n function evilSeize(VToken treasure, address liquidator, address borrower, uint seizeTokens) public returns (uint) {\n return treasure.seize(liquidator, borrower, seizeTokens);\n }\n}\n\nabstract contract VBep20DelegatorScenario is VBep20Delegator {\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n )\n VBep20Delegator(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_,\n admin_,\n implementation_,\n becomeImplementationData\n )\n {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n}\n\ncontract VBep20DelegateHarness is VBep20Delegate {\n event Log(string x, address y);\n event Log(string x, uint y);\n\n uint internal blockNumber = 100000;\n uint internal harnessExchangeRate;\n bool internal harnessExchangeRateStored;\n\n mapping(address => bool) public failTransferToAddresses;\n\n function exchangeRateStoredInternal() internal view override returns (MathError, uint) {\n if (harnessExchangeRateStored) {\n return (MathError.NO_ERROR, harnessExchangeRate);\n }\n return super.exchangeRateStoredInternal();\n }\n\n function doTransferOut(address payable to, uint amount) internal override {\n require(failTransferToAddresses[to] == false, \"TOKEN_TRANSFER_OUT_FAILED\");\n return super.doTransferOut(to, amount);\n }\n\n function getBlockNumber() internal view returns (uint) {\n return blockNumber;\n }\n\n function getBorrowRateMaxMantissa() public pure returns (uint) {\n return borrowRateMaxMantissa;\n }\n\n function harnessSetBlockNumber(uint newBlockNumber) public {\n blockNumber = newBlockNumber;\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n function harnessSetBalance(address account, uint amount) external {\n accountTokens[account] = amount;\n }\n\n function harnessSetAccrualBlockNumber(uint _accrualblockNumber) public {\n accrualBlockNumber = _accrualblockNumber;\n }\n\n function harnessSetTotalSupply(uint totalSupply_) public {\n totalSupply = totalSupply_;\n }\n\n function harnessSetTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function harnessIncrementTotalBorrows(uint addtlBorrow_) public {\n totalBorrows = totalBorrows + addtlBorrow_;\n }\n\n function harnessSetTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function harnessExchangeRateDetails(uint totalSupply_, uint totalBorrows_, uint totalReserves_) public {\n totalSupply = totalSupply_;\n totalBorrows = totalBorrows_;\n totalReserves = totalReserves_;\n }\n\n function harnessSetExchangeRate(uint exchangeRate) public {\n harnessExchangeRate = exchangeRate;\n harnessExchangeRateStored = true;\n }\n\n function harnessSetFailTransferToAddress(address _to, bool _fail) public {\n failTransferToAddresses[_to] = _fail;\n }\n\n function harnessMintFresh(address account, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintFresh(account, mintAmount);\n return err;\n }\n\n function harnessMintBehalfFresh(address payer, address receiver, uint mintAmount) public returns (uint) {\n (uint err, ) = super.mintBehalfFresh(payer, receiver, mintAmount);\n return err;\n }\n\n function harnessRedeemFresh(\n address payable account,\n uint vTokenAmount,\n uint underlyingAmount\n ) public returns (uint) {\n return super.redeemFresh(account, account, vTokenAmount, underlyingAmount);\n }\n\n function harnessAccountBorrows(address account) public view returns (uint principal, uint interestIndex) {\n BorrowSnapshot memory snapshot = accountBorrows[account];\n return (snapshot.principal, snapshot.interestIndex);\n }\n\n function harnessSetAccountBorrows(address account, uint principal, uint interestIndex) public {\n accountBorrows[account] = BorrowSnapshot({ principal: principal, interestIndex: interestIndex });\n }\n\n function harnessSetBorrowIndex(uint borrowIndex_) public {\n borrowIndex = borrowIndex_;\n }\n\n function harnessBorrowFresh(address payable account, uint borrowAmount) public returns (uint) {\n return borrowFresh(account, account, borrowAmount, true);\n }\n\n function harnessRepayBorrowFresh(address payer, address account, uint repayAmount) public returns (uint) {\n (uint err, ) = repayBorrowFresh(payer, account, repayAmount);\n return err;\n }\n\n function harnessLiquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VToken vTokenCollateral\n ) public returns (uint) {\n (uint err, ) = liquidateBorrowFresh(liquidator, borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n function harnessReduceReservesFresh(uint amount) public returns (uint) {\n return _reduceReservesFresh(amount);\n }\n\n function harnessSetReserveFactorFresh(uint newReserveFactorMantissa) public returns (uint) {\n return _setReserveFactorFresh(newReserveFactorMantissa);\n }\n\n function harnessSetInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) public returns (uint) {\n return _setInterestRateModelFresh(newInterestRateModel);\n }\n\n function harnessSetInterestRateModel(address newInterestRateModelAddress) public {\n interestRateModel = InterestRateModelV8(newInterestRateModelAddress);\n }\n\n function harnessCallBorrowAllowed(uint amount) public returns (uint) {\n return comptroller.borrowAllowed(address(this), msg.sender, amount);\n }\n\n function harnessSetInternalCash(uint256 _internalCash) public {\n internalCash = _internalCash;\n }\n}\n\ncontract VBep20DelegateScenario is VBep20Delegate {\n constructor() {}\n\n function setTotalBorrows(uint totalBorrows_) public {\n totalBorrows = totalBorrows_;\n }\n\n function setTotalReserves(uint totalReserves_) public {\n totalReserves = totalReserves_;\n }\n\n function getBlockNumber() internal view returns (uint) {\n ComptrollerScenario comptrollerScenario = ComptrollerScenario(address(comptroller));\n return comptrollerScenario.blockNumber();\n }\n}\n\ncontract VBep20DelegateScenarioExtra is VBep20DelegateScenario {\n function iHaveSpoken() public pure returns (string memory) {\n return \"i have spoken\";\n }\n\n function itIsTheWay() public {\n admin = payable(address(1)); // make a change to test effect\n }\n\n function babyYoda() public pure {\n revert(\"protect the baby\");\n }\n}\n" + }, + "contracts/test/VBep20MockDelegate.sol": { + "content": "pragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport { ComptrollerInterface } from \"../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../Tokens/VTokens/VToken.sol\";\nimport { InterestRateModelV8 } from \"../InterestRateModels/InterestRateModelV8.sol\";\nimport { VBep20Interface, VTokenInterface } from \"../Tokens/VTokens/VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20 Contract\n * @notice VTokens which wrap an EIP-20 underlying\n * @author Venus\n */\ncontract VBep20MockDelegate is VToken, VBep20Interface {\n using SafeERC20 for IERC20;\n\n uint internal blockNumber = 100000;\n\n /**\n * @notice Initialize the new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n // VToken initialize does the bulk of the work\n super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20(underlying).totalSupply();\n }\n\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) public {\n // Shh -- currently unused\n data;\n\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _becomeImplementation\");\n }\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() public {\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _resignImplementation\");\n }\n\n function harnessFastForward(uint blocks) public {\n blockNumber += blocks;\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mint(uint mintAmount) external returns (uint) {\n (uint err, ) = mintInternal(mintAmount);\n return err;\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver the account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n (uint err, ) = mintBehalfInternal(receiver, mintAmount);\n return err;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrow(uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @param borrower the account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\n return err;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n (uint err, ) = liquidateBorrowInternal(borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount fo underlying token to add as reserves\n * @return uint 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _addReserves(uint addAmount) external returns (uint) {\n return _addReservesInternal(addAmount);\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets the tracked internal cash balance of this contract\n * @dev Returns `internalCash` rather than the actual token balance, making it immune to donation attacks.\n * @return The internally tracked cash balance of underlying tokens\n */\n function getCashPrior() internal view override returns (uint) {\n return internalCash;\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.\n * This will revert due to insufficient balance or insufficient allowance.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n * Increments `internalCash` by the actual amount received.\n *\n * Note: This wrapper safely handles non-standard BEP-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferIn(address from, uint amount) internal override returns (uint) {\n IERC20 token = IERC20(underlying);\n uint balanceBefore = IERC20(underlying).balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n // Calculate the amount that was *actually* transferred\n uint balanceAfter = IERC20(underlying).balanceOf(address(this));\n uint actualAmount = balanceAfter - balanceBefore;\n internalCash += actualAmount;\n return actualAmount;\n }\n\n /**\n * @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory\n * error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to\n * insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified\n * it is >= amount, this should not revert in normal conditions.\n * Decrements `internalCash` by `amount` before transferring.\n *\n * Note: This wrapper safely handles non-standard BEP-20 tokens that do not return a value.\n * See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\n function doTransferOut(address payable to, uint amount) internal override {\n internalCash -= amount;\n IERC20 token = IERC20(underlying);\n token.safeTransfer(to, amount);\n }\n\n function harnessSetInternalCash(uint256 _internalCash) public {\n internalCash = _internalCash;\n }\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/InterfaceComptroller.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0-or-later\npragma solidity ^0.8.25;\n\ninterface InterfaceComptroller {\n function markets(address) external view returns (bool);\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IPoolRegistry.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\n/**\n * @title PoolRegistryInterface\n * @author Venus\n * @notice Interface implemented by `PoolRegistry`.\n */\ninterface PoolRegistryInterface {\n /**\n * @notice Struct for a Venus interest rate pool.\n */\n struct VenusPool {\n string name;\n address creator;\n address comptroller;\n uint256 blockPosted;\n uint256 timestampPosted;\n }\n\n /// @notice Get a pool by comptroller address\n function getPoolByComptroller(address comptroller) external view returns (VenusPool memory);\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IPrime.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { PrimeStorageV1 } from \"../PrimeStorage.sol\";\n\n/**\n * @title IPrime\n * @author Venus\n * @notice Interface for Prime Token\n */\ninterface IPrime {\n struct APRInfo {\n // supply APR of the user in BPS\n uint256 supplyAPR;\n // borrow APR of the user in BPS\n uint256 borrowAPR;\n // total score of the market\n uint256 totalScore;\n // score of the user\n uint256 userScore;\n // capped XVS balance of the user\n uint256 xvsBalanceForScore;\n // capital of the user\n uint256 capital;\n // capped supply of the user\n uint256 cappedSupply;\n // capped borrow of the user\n uint256 cappedBorrow;\n // capped supply of user in USD\n uint256 supplyCapUSD;\n // capped borrow of user in USD\n uint256 borrowCapUSD;\n }\n\n struct Capital {\n // capital of the user\n uint256 capital;\n // capped supply of the user\n uint256 cappedSupply;\n // capped borrow of the user\n uint256 cappedBorrow;\n // capped supply of user in USD\n uint256 supplyCapUSD;\n // capped borrow of user in USD\n uint256 borrowCapUSD;\n }\n\n /**\n * @notice Returns boosted pending interest accrued for a user for all markets\n * @param user the account for which to get the accrued interests\n * @return pendingRewards the number of underlying tokens accrued by the user for all markets\n */\n function getPendingRewards(address user) external returns (PrimeStorageV1.PendingReward[] memory pendingRewards);\n\n /**\n * @notice Update total score of multiple users and market\n * @param users accounts for which we need to update score\n */\n function updateScores(address[] memory users) external;\n\n /**\n * @notice Update value of alpha\n * @param _alphaNumerator numerator of alpha. If alpha is 0.5 then numerator is 1\n * @param _alphaDenominator denominator of alpha. If alpha is 0.5 then denominator is 2\n */\n function updateAlpha(uint128 _alphaNumerator, uint128 _alphaDenominator) external;\n\n /**\n * @notice Update multipliers for a market\n * @param market address of the market vToken\n * @param supplyMultiplier new supply multiplier for the market, scaled by 1e18\n * @param borrowMultiplier new borrow multiplier for the market, scaled by 1e18\n */\n function updateMultipliers(address market, uint256 supplyMultiplier, uint256 borrowMultiplier) external;\n\n /**\n * @notice Add a market to prime program\n * @param comptroller address of the comptroller\n * @param market address of the market vToken\n * @param supplyMultiplier the multiplier for supply cap. It should be converted to 1e18\n * @param borrowMultiplier the multiplier for borrow cap. It should be converted to 1e18\n */\n function addMarket(\n address comptroller,\n address market,\n uint256 supplyMultiplier,\n uint256 borrowMultiplier\n ) external;\n\n /**\n * @notice Set limits for total tokens that can be minted\n * @param _irrevocableLimit total number of irrevocable tokens that can be minted\n * @param _revocableLimit total number of revocable tokens that can be minted\n */\n function setLimit(uint256 _irrevocableLimit, uint256 _revocableLimit) external;\n\n /**\n * @notice Directly issue prime tokens to users\n * @param isIrrevocable are the tokens being issued\n * @param users list of address to issue tokens to\n */\n function issue(bool isIrrevocable, address[] calldata users) external;\n\n /**\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\n * @param user the account address whose balance was updated\n */\n function xvsUpdated(address user) external;\n\n /**\n * @notice accrues interest and updates score for an user for a specific market\n * @param user the account address for which to accrue interest and update score\n * @param market the market for which to accrue interest and update score\n */\n function accrueInterestAndUpdateScore(address user, address market) external;\n\n /**\n * @notice For claiming prime token when staking period is completed\n */\n function claim() external;\n\n /**\n * @notice For burning any prime token\n * @param user the account address for which the prime token will be burned\n */\n function burn(address user) external;\n\n /**\n * @notice To pause or unpause claiming of interest\n */\n function togglePause() external;\n\n /**\n * @notice For user to claim boosted yield\n * @param vToken the market for which claim the accrued interest\n * @return amount the amount of tokens transferred to the user\n */\n function claimInterest(address vToken) external returns (uint256);\n\n /**\n * @notice For user to claim boosted yield\n * @param vToken the market for which claim the accrued interest\n * @param user the user for which to claim the accrued interest\n * @return amount the amount of tokens transferred to the user\n */\n function claimInterest(address vToken, address user) external returns (uint256);\n\n /**\n * @notice Distributes income from market since last distribution\n * @param vToken the market for which to distribute the income\n */\n function accrueInterest(address vToken) external;\n\n /**\n * @notice Returns boosted interest accrued for a user\n * @param vToken the market for which to fetch the accrued interest\n * @param user the account for which to get the accrued interest\n * @return interestAccrued the number of underlying tokens accrued by the user since the last accrual\n */\n function getInterestAccrued(address vToken, address user) external returns (uint256);\n\n /**\n * @notice Retrieves an array of all available markets\n * @return an array of addresses representing all available markets\n */\n function getAllMarkets() external view returns (address[] memory);\n\n /**\n * @notice fetch the numbers of seconds remaining for staking period to complete\n * @param user the account address for which we are checking the remaining time\n * @return timeRemaining the number of seconds the user needs to wait to claim prime token\n */\n function claimTimeRemaining(address user) external view returns (uint256);\n\n /**\n * @notice Returns supply and borrow APR for user for a given market\n * @param market the market for which to fetch the APR\n * @param user the account for which to get the APR\n * @return aprInfo APR information for the user for the given market\n */\n function calculateAPR(address market, address user) external view returns (APRInfo memory aprInfo);\n\n /**\n * @notice Returns supply and borrow APR for estimated supply, borrow and XVS staked\n * @param market the market for which to fetch the APR\n * @param user the account for which to get the APR\n * @param borrow hypothetical borrow amount\n * @param supply hypothetical supply amount\n * @param xvsStaked hypothetical staked XVS amount\n * @return aprInfo APR information for the user for the given market\n */\n function estimateAPR(\n address market,\n address user,\n uint256 borrow,\n uint256 supply,\n uint256 xvsStaked\n ) external view returns (APRInfo memory aprInfo);\n\n /**\n * @notice the total income that's going to be distributed in a year to prime token holders\n * @param vToken the market for which to fetch the total income that's going to distributed in a year\n * @return amount the total income\n */\n function incomeDistributionYearly(address vToken) external view returns (uint256 amount);\n\n /**\n * @notice Returns if user is a prime holder\n * @return isPrimeHolder true if user is a prime holder\n */\n function isUserPrimeHolder(address user) external view returns (bool);\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param loopsLimit Number of loops limit\n */\n function setMaxLoopsLimit(uint256 loopsLimit) external;\n\n /**\n * @notice Update staked at timestamp for multiple users\n * @param users accounts for which we need to update staked at timestamp\n * @param timestamps new staked at timestamp for the users\n */\n function setStakedAt(address[] calldata users, uint256[] calldata timestamps) external;\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IPrimeLiquidityProvider.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\nimport { IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\n\n/**\n * @title IPrimeLiquidityProvider\n * @author Venus\n * @notice Interface for PrimeLiquidityProvider\n */\ninterface IPrimeLiquidityProvider {\n /**\n * @notice Initialize the distribution of the token\n * @param tokens_ Array of addresses of the tokens to be intialized\n */\n function initializeTokens(address[] calldata tokens_) external;\n\n /**\n * @notice Pause fund transfer of tokens to Prime contract\n */\n function pauseFundsTransfer() external;\n\n /**\n * @notice Resume fund transfer of tokens to Prime contract\n */\n function resumeFundsTransfer() external;\n\n /**\n * @notice Set distribution speed (amount of token distribute per block or second)\n * @param tokens_ Array of addresses of the tokens\n * @param distributionSpeeds_ New distribution speeds for tokens\n */\n function setTokensDistributionSpeed(address[] calldata tokens_, uint256[] calldata distributionSpeeds_) external;\n\n /**\n * @notice Set max distribution speed for token (amount of maximum token distribute per block or second)\n * @param tokens_ Array of addresses of the tokens\n * @param maxDistributionSpeeds_ New distribution speeds for tokens\n */\n function setMaxTokensDistributionSpeed(\n address[] calldata tokens_,\n uint256[] calldata maxDistributionSpeeds_\n ) external;\n\n /**\n * @notice Set the prime token contract address\n * @param prime_ The new address of the prime token contract\n */\n function setPrimeToken(address prime_) external;\n\n /**\n * @notice Claim all the token accrued till last block or second\n * @param token_ The token to release to the Prime contract\n */\n function releaseFunds(address token_) external;\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to user\n * @param token_ The address of the ERC-20 token to sweep\n * @param to_ The address of the recipient\n * @param amount_ The amount of tokens needs to transfer\n */\n function sweepToken(IERC20Upgradeable token_, address to_, uint256 amount_) external;\n\n /**\n * @notice Accrue token by updating the distribution state\n * @param token_ Address of the token\n */\n function accrueTokens(address token_) external;\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param loopsLimit Limit for the max loops can execute at a time\n */\n function setMaxLoopsLimit(uint256 loopsLimit) external;\n\n /**\n * @notice Get rewards per block or second for token\n * @param token_ Address of the token\n * @return speed returns the per block or second reward\n */\n function getEffectiveDistributionSpeed(address token_) external view returns (uint256);\n\n /**\n * @notice Get the amount of tokens accrued\n * @param token_ Address of the token\n * @return Amount of tokens that are accrued\n */\n function tokenAmountAccrued(address token_) external view returns (uint256);\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IVToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IVToken {\n function borrowBalanceStored(address account) external view returns (uint256);\n\n function exchangeRateStored() external view returns (uint256);\n\n function balanceOf(address account) external view returns (uint256);\n\n function underlying() external view returns (address);\n\n function totalBorrows() external view returns (uint256);\n\n function borrowRatePerBlock() external view returns (uint256);\n\n function reserveFactorMantissa() external view returns (uint256);\n\n function decimals() external view returns (uint8);\n}\n" + }, + "contracts/Tokens/Prime/Interfaces/IXVSVault.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity ^0.8.25;\n\ninterface IXVSVault {\n function getUserInfo(\n address _rewardToken,\n uint256 _pid,\n address _user\n ) external view returns (uint256 amount, uint256 rewardDebt, uint256 pendingWithdrawals);\n\n function xvsAddress() external view returns (address);\n}\n" + }, + "contracts/Tokens/Prime/IPrime.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title IPrime\n * @author Venus\n * @notice Interface for Prime Token\n */\ninterface IPrime {\n /**\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\n * @param user the account address whose balance was updated\n */\n function xvsUpdated(address user) external;\n\n /**\n * @notice accrues interest and updates score for an user for a specific market\n * @param user the account address for which to accrue interest and update score\n * @param market the market for which to accrue interest and update score\n */\n function accrueInterestAndUpdateScore(address user, address market) external;\n\n /**\n * @notice Distributes income from market since last distribution\n * @param vToken the market for which to distribute the income\n */\n function accrueInterest(address vToken) external;\n\n /**\n * @notice Returns if user is a prime holder\n * @param isPrimeHolder returns if the user is a prime holder\n */\n function isUserPrimeHolder(address user) external view returns (bool isPrimeHolder);\n}\n" + }, + "contracts/Tokens/Prime/libs/FixedMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable var-name-mixedcase\n\npragma solidity 0.8.25;\n\nimport { SafeCastUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol\";\nimport { FixedMath0x } from \"./FixedMath0x.sol\";\n\nusing SafeCastUpgradeable for uint256;\n\nerror InvalidFixedPoint();\n\n/**\n * @title FixedMath\n * @author Venus\n * @notice FixedMath library is used for complex mathematical operations\n */\nlibrary FixedMath {\n error InvalidFraction(uint256 n, uint256 d);\n\n /**\n * @notice Convert some uint256 fraction `n` numerator / `d` denominator to a fixed-point number `f`.\n * @param n numerator\n * @param d denominator\n * @return fixed-point number\n */\n function _toFixed(uint256 n, uint256 d) internal pure returns (int256) {\n if (d.toInt256() < n.toInt256()) revert InvalidFraction(n, d);\n\n return (n.toInt256() * FixedMath0x.FIXED_1) / int256(d.toInt256());\n }\n\n /**\n * @notice Divide some unsigned int `u` by a fixed point number `f`\n * @param u unsigned dividend\n * @param f fixed point divisor, in FIXED_1 units\n * @return unsigned int quotient\n */\n function _uintDiv(uint256 u, int256 f) internal pure returns (uint256) {\n if (f < 0) revert InvalidFixedPoint();\n // multiply `u` by FIXED_1 to cancel out the built-in FIXED_1 in f\n return uint256((u.toInt256() * FixedMath0x.FIXED_1) / f);\n }\n\n /**\n * @notice Multiply some unsigned int `u` by a fixed point number `f`\n * @param u unsigned multiplicand\n * @param f fixed point multiplier, in FIXED_1 units\n * @return unsigned int product\n */\n function _uintMul(uint256 u, int256 f) internal pure returns (uint256) {\n if (f < 0) revert InvalidFixedPoint();\n // divide the product by FIXED_1 to cancel out the built-in FIXED_1 in f\n return uint256((u.toInt256() * f) / FixedMath0x.FIXED_1);\n }\n\n /// @notice see FixedMath0x\n function _ln(int256 x) internal pure returns (int256) {\n return FixedMath0x._ln(x);\n }\n\n /// @notice see FixedMath0x\n function _exp(int256 x) internal pure returns (int256) {\n return FixedMath0x._exp(x);\n }\n}\n" + }, + "contracts/Tokens/Prime/libs/FixedMath0x.sol": { + "content": "// SPDX-License-Identifier: MIT\n// solhint-disable max-line-length\n\npragma solidity 0.8.25;\n\n// Below is code from 0x's LibFixedMath.sol. Changes:\n// - addition of 0.8-style errors\n// - removal of unused functions\n// - added comments for clarity\n// https://github.com/0xProject/exchange-v3/blob/aae46bef841bfd1cc31028f41793db4fe7197084/contracts/staking/contracts/src/libs/LibFixedMath.sol\n\n/*\n\n Copyright 2017 Bprotocol Foundation, 2019 ZeroEx Intl.\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n*/\n/// Thrown when the natural log function is given too large of an argument\nerror LnTooLarge(int256 x);\n/// Thrown when the natural log would have returned a number outside of ℝ\nerror LnNonRealResult(int256 x);\n/// Thrown when exp is given too large of an argument\nerror ExpTooLarge(int256 x);\n/// Thrown when an unsigned value is too large to be converted to a signed value\nerror UnsignedValueTooLarge(uint256 x);\n\n/**\n * @title FixedMath0x\n * @notice Signed, fixed-point, 127-bit precision math library\n */\nlibrary FixedMath0x {\n // Base for the fixed point numbers (this is our 1)\n int256 internal constant FIXED_1 = int256(0x0000000000000000000000000000000080000000000000000000000000000000);\n // Maximum ln argument (1)\n int256 private constant LN_MAX_VAL = FIXED_1;\n // Minimum ln argument. Notice this is related to EXP_MIN_VAL (e ^ -63.875)\n int256 private constant LN_MIN_VAL = int256(0x0000000000000000000000000000000000000000000000000000000733048c5a);\n // Maximum exp argument (0)\n int256 private constant EXP_MAX_VAL = 0;\n // Minimum exp argument. Notice this is related to LN_MIN_VAL (-63.875)\n int256 private constant EXP_MIN_VAL = -int256(0x0000000000000000000000000000001ff0000000000000000000000000000000);\n\n /// @dev Get the natural logarithm of a fixed-point number 0 < `x` <= LN_MAX_VAL\n function _ln(int256 x) internal pure returns (int256 r) {\n if (x > LN_MAX_VAL) {\n revert LnTooLarge(x);\n }\n if (x <= 0) {\n revert LnNonRealResult(x);\n }\n if (x == FIXED_1) {\n return 0;\n }\n if (x <= LN_MIN_VAL) {\n return EXP_MIN_VAL;\n }\n\n int256 y;\n int256 z;\n int256 w;\n\n // Rewrite the input as a quotient of negative natural exponents and a single residual q, such that 1 < q < 2\n // For example: log(0.3) = log(e^-1 * e^-0.25 * 1.0471028872385522)\n // = 1 - 0.25 - log(1 + 0.0471028872385522)\n // e ^ -32\n if (x <= int256(0x00000000000000000000000000000000000000000001c8464f76164760000000)) {\n r -= int256(0x0000000000000000000000000000001000000000000000000000000000000000); // - 32\n x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000000001c8464f76164760000000); // / e ^ -32\n }\n // e ^ -16\n if (x <= int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000)) {\n r -= int256(0x0000000000000000000000000000000800000000000000000000000000000000); // - 16\n x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000000f1aaddd7742e90000000000000); // / e ^ -16\n }\n // e ^ -8\n if (x <= int256(0x00000000000000000000000000000000000afe10820813d78000000000000000)) {\n r -= int256(0x0000000000000000000000000000000400000000000000000000000000000000); // - 8\n x = (x * FIXED_1) / int256(0x00000000000000000000000000000000000afe10820813d78000000000000000); // / e ^ -8\n }\n // e ^ -4\n if (x <= int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000)) {\n r -= int256(0x0000000000000000000000000000000200000000000000000000000000000000); // - 4\n x = (x * FIXED_1) / int256(0x0000000000000000000000000000000002582ab704279ec00000000000000000); // / e ^ -4\n }\n // e ^ -2\n if (x <= int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000)) {\n r -= int256(0x0000000000000000000000000000000100000000000000000000000000000000); // - 2\n x = (x * FIXED_1) / int256(0x000000000000000000000000000000001152aaa3bf81cc000000000000000000); // / e ^ -2\n }\n // e ^ -1\n if (x <= int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000)) {\n r -= int256(0x0000000000000000000000000000000080000000000000000000000000000000); // - 1\n x = (x * FIXED_1) / int256(0x000000000000000000000000000000002f16ac6c59de70000000000000000000); // / e ^ -1\n }\n // e ^ -0.5\n if (x <= int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000)) {\n r -= int256(0x0000000000000000000000000000000040000000000000000000000000000000); // - 0.5\n x = (x * FIXED_1) / int256(0x000000000000000000000000000000004da2cbf1be5828000000000000000000); // / e ^ -0.5\n }\n // e ^ -0.25\n if (x <= int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000)) {\n r -= int256(0x0000000000000000000000000000000020000000000000000000000000000000); // - 0.25\n x = (x * FIXED_1) / int256(0x0000000000000000000000000000000063afbe7ab2082c000000000000000000); // / e ^ -0.25\n }\n // e ^ -0.125\n if (x <= int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d)) {\n r -= int256(0x0000000000000000000000000000000010000000000000000000000000000000); // - 0.125\n x = (x * FIXED_1) / int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d); // / e ^ -0.125\n }\n // `x` is now our residual in the range of 1 <= x <= 2 (or close enough).\n\n // Add the taylor series for log(1 + z), where z = x - 1\n z = y = x - FIXED_1;\n w = (y * y) / FIXED_1;\n r += (z * (0x100000000000000000000000000000000 - y)) / 0x100000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^01 / 01 - y^02 / 02\n r += (z * (0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - y)) / 0x200000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^03 / 03 - y^04 / 04\n r += (z * (0x099999999999999999999999999999999 - y)) / 0x300000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^05 / 05 - y^06 / 06\n r += (z * (0x092492492492492492492492492492492 - y)) / 0x400000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^07 / 07 - y^08 / 08\n r += (z * (0x08e38e38e38e38e38e38e38e38e38e38e - y)) / 0x500000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^09 / 09 - y^10 / 10\n r += (z * (0x08ba2e8ba2e8ba2e8ba2e8ba2e8ba2e8b - y)) / 0x600000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^11 / 11 - y^12 / 12\n r += (z * (0x089d89d89d89d89d89d89d89d89d89d89 - y)) / 0x700000000000000000000000000000000;\n z = (z * w) / FIXED_1; // add y^13 / 13 - y^14 / 14\n r += (z * (0x088888888888888888888888888888888 - y)) / 0x800000000000000000000000000000000; // add y^15 / 15 - y^16 / 16\n }\n\n /// @dev Compute the natural exponent for a fixed-point number EXP_MIN_VAL <= `x` <= 1\n function _exp(int256 x) internal pure returns (int256 r) {\n if (x < EXP_MIN_VAL) {\n // Saturate to zero below EXP_MIN_VAL.\n return 0;\n }\n if (x == 0) {\n return FIXED_1;\n }\n if (x > EXP_MAX_VAL) {\n revert ExpTooLarge(x);\n }\n\n // Rewrite the input as a product of natural exponents and a\n // single residual q, where q is a number of small magnitude.\n // For example: e^-34.419 = e^(-32 - 2 - 0.25 - 0.125 - 0.044)\n // = e^-32 * e^-2 * e^-0.25 * e^-0.125 * e^-0.044\n // -> q = -0.044\n\n // Multiply with the taylor series for e^q\n int256 y;\n int256 z;\n // q = x % 0.125 (the residual)\n z = y = x % 0x0000000000000000000000000000000010000000000000000000000000000000;\n z = (z * y) / FIXED_1;\n r += z * 0x10e1b3be415a0000; // add y^02 * (20! / 02!)\n z = (z * y) / FIXED_1;\n r += z * 0x05a0913f6b1e0000; // add y^03 * (20! / 03!)\n z = (z * y) / FIXED_1;\n r += z * 0x0168244fdac78000; // add y^04 * (20! / 04!)\n z = (z * y) / FIXED_1;\n r += z * 0x004807432bc18000; // add y^05 * (20! / 05!)\n z = (z * y) / FIXED_1;\n r += z * 0x000c0135dca04000; // add y^06 * (20! / 06!)\n z = (z * y) / FIXED_1;\n r += z * 0x0001b707b1cdc000; // add y^07 * (20! / 07!)\n z = (z * y) / FIXED_1;\n r += z * 0x000036e0f639b800; // add y^08 * (20! / 08!)\n z = (z * y) / FIXED_1;\n r += z * 0x00000618fee9f800; // add y^09 * (20! / 09!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000009c197dcc00; // add y^10 * (20! / 10!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000e30dce400; // add y^11 * (20! / 11!)\n z = (z * y) / FIXED_1;\n r += z * 0x000000012ebd1300; // add y^12 * (20! / 12!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000017499f00; // add y^13 * (20! / 13!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000001a9d480; // add y^14 * (20! / 14!)\n z = (z * y) / FIXED_1;\n r += z * 0x00000000001c6380; // add y^15 * (20! / 15!)\n z = (z * y) / FIXED_1;\n r += z * 0x000000000001c638; // add y^16 * (20! / 16!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000000001ab8; // add y^17 * (20! / 17!)\n z = (z * y) / FIXED_1;\n r += z * 0x000000000000017c; // add y^18 * (20! / 18!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000000000014; // add y^19 * (20! / 19!)\n z = (z * y) / FIXED_1;\n r += z * 0x0000000000000001; // add y^20 * (20! / 20!)\n r = r / 0x21c3677c82b40000 + y + FIXED_1; // divide by 20! and then add y^1 / 1! + y^0 / 0!\n\n // Multiply with the non-residual terms.\n x = -x;\n // e ^ -32\n if ((x & int256(0x0000000000000000000000000000001000000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x00000000000000000000000000000000000000f1aaddd7742e56d32fb9f99744)) /\n int256(0x0000000000000000000000000043cbaf42a000812488fc5c220ad7b97bf6e99e); // * e ^ -32\n }\n // e ^ -16\n if ((x & int256(0x0000000000000000000000000000000800000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x00000000000000000000000000000000000afe10820813d65dfe6a33c07f738f)) /\n int256(0x000000000000000000000000000005d27a9f51c31b7c2f8038212a0574779991); // * e ^ -16\n }\n // e ^ -8\n if ((x & int256(0x0000000000000000000000000000000400000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x0000000000000000000000000000000002582ab704279e8efd15e0265855c47a)) /\n int256(0x0000000000000000000000000000001b4c902e273a58678d6d3bfdb93db96d02); // * e ^ -8\n }\n // e ^ -4\n if ((x & int256(0x0000000000000000000000000000000200000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x000000000000000000000000000000001152aaa3bf81cb9fdb76eae12d029571)) /\n int256(0x00000000000000000000000000000003b1cc971a9bb5b9867477440d6d157750); // * e ^ -4\n }\n // e ^ -2\n if ((x & int256(0x0000000000000000000000000000000100000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x000000000000000000000000000000002f16ac6c59de6f8d5d6f63c1482a7c86)) /\n int256(0x000000000000000000000000000000015bf0a8b1457695355fb8ac404e7a79e3); // * e ^ -2\n }\n // e ^ -1\n if ((x & int256(0x0000000000000000000000000000000080000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x000000000000000000000000000000004da2cbf1be5827f9eb3ad1aa9866ebb3)) /\n int256(0x00000000000000000000000000000000d3094c70f034de4b96ff7d5b6f99fcd8); // * e ^ -1\n }\n // e ^ -0.5\n if ((x & int256(0x0000000000000000000000000000000040000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x0000000000000000000000000000000063afbe7ab2082ba1a0ae5e4eb1b479dc)) /\n int256(0x00000000000000000000000000000000a45af1e1f40c333b3de1db4dd55f29a7); // * e ^ -0.5\n }\n // e ^ -0.25\n if ((x & int256(0x0000000000000000000000000000000020000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x0000000000000000000000000000000070f5a893b608861e1f58934f97aea57d)) /\n int256(0x00000000000000000000000000000000910b022db7ae67ce76b441c27035c6a1); // * e ^ -0.25\n }\n // e ^ -0.125\n if ((x & int256(0x0000000000000000000000000000000010000000000000000000000000000000)) != 0) {\n r =\n (r * int256(0x00000000000000000000000000000000783eafef1c0a8f3978c7f81824d62ebf)) /\n int256(0x0000000000000000000000000000000088415abbe9a76bead8d00cf112e4d4a8); // * e ^ -0.125\n }\n }\n}\n" + }, + "contracts/Tokens/Prime/libs/Scores.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.25;\n\nimport { SafeCastUpgradeable } from \"@openzeppelin/contracts-upgradeable/utils/math/SafeCastUpgradeable.sol\";\nimport { FixedMath } from \"./FixedMath.sol\";\n\nusing SafeCastUpgradeable for uint256;\n\n/**\n * @title Scores\n * @author Venus\n * @notice Scores library is used to calculate score of users\n */\nlibrary Scores {\n /**\n * @notice Calculate a membership score given some amount of `xvs` and `capital`, along\n * with some 𝝰 = `alphaNumerator` / `alphaDenominator`.\n * @param xvs amount of xvs (xvs, 1e18 decimal places)\n * @param capital amount of capital (1e18 decimal places)\n * @param alphaNumerator alpha param numerator\n * @param alphaDenominator alpha param denominator\n * @return membership score with 1e18 decimal places\n *\n * @dev 𝝰 must be in the range [0, 1]\n */\n function _calculateScore(\n uint256 xvs,\n uint256 capital,\n uint256 alphaNumerator,\n uint256 alphaDenominator\n ) internal pure returns (uint256) {\n // Score function is:\n // xvs^𝝰 * capital^(1-𝝰)\n // = capital * capital^(-𝝰) * xvs^𝝰\n // = capital * (xvs / capital)^𝝰\n // = capital * (e ^ (ln(xvs / capital))) ^ 𝝰\n // = capital * e ^ (𝝰 * ln(xvs / capital)) (1)\n // or\n // = capital / ( 1 / e ^ (𝝰 * ln(xvs / capital)))\n // = capital / (e ^ (𝝰 * ln(xvs / capital)) ^ -1)\n // = capital / e ^ (𝝰 * -1 * ln(xvs / capital))\n // = capital / e ^ (𝝰 * ln(capital / xvs)) (2)\n //\n // To avoid overflows, use (1) when xvs < capital and\n // use (2) when capital < xvs\n\n // If any side is 0, exit early\n if (xvs == 0 || capital == 0) return 0;\n\n // If both sides are equal, we have:\n // xvs^𝝰 * capital^(1-𝝰)\n // = xvs^𝝰 * xvs^(1-𝝰)\n // = xvs^(𝝰 + 1 - 𝝰) = xvs\n if (xvs == capital) return xvs;\n\n bool lessxvsThanCapital = xvs < capital;\n\n // (xvs / capital) or (capital / xvs), always in range (0, 1)\n int256 ratio = lessxvsThanCapital ? FixedMath._toFixed(xvs, capital) : FixedMath._toFixed(capital, xvs);\n\n // e ^ ( ln(ratio) * 𝝰 )\n int256 exponentiation = FixedMath._exp(\n (FixedMath._ln(ratio) * alphaNumerator.toInt256()) / alphaDenominator.toInt256()\n );\n\n if (lessxvsThanCapital) {\n // capital * e ^ (𝝰 * ln(xvs / capital))\n return FixedMath._uintMul(capital, exponentiation);\n }\n\n // capital / e ^ (𝝰 * ln(capital / xvs))\n return FixedMath._uintDiv(capital, exponentiation);\n }\n}\n" + }, + "contracts/Tokens/Prime/Prime.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\nimport { IERC20MetadataUpgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol\";\n\nimport { PrimeStorageV1 } from \"./PrimeStorage.sol\";\nimport { Scores } from \"./libs/Scores.sol\";\n\nimport { IPrimeLiquidityProvider } from \"./Interfaces/IPrimeLiquidityProvider.sol\";\nimport { IPrime } from \"./Interfaces/IPrime.sol\";\nimport { IXVSVault } from \"./Interfaces/IXVSVault.sol\";\nimport { IVToken } from \"./Interfaces/IVToken.sol\";\nimport { InterfaceComptroller } from \"./Interfaces/InterfaceComptroller.sol\";\nimport { PoolRegistryInterface } from \"./Interfaces/IPoolRegistry.sol\";\n\n/**\n * @title Prime\n * @author Venus\n * @notice Prime Token is used to provide extra rewards to the users who have staked a minimum of `MINIMUM_STAKED_XVS` XVS in the XVSVault for `STAKING_PERIOD` days\n * @custom:security-contact https://github.com/VenusProtocol/venus-protocol\n */\ncontract Prime is IPrime, AccessControlledV8, PausableUpgradeable, MaxLoopsLimitHelper, PrimeStorageV1, TimeManagerV8 {\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice address of wrapped native token contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable WRAPPED_NATIVE_TOKEN;\n\n /// @notice address of native market contract\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n address public immutable NATIVE_MARKET;\n\n /// @notice minimum amount of XVS user needs to stake to become a prime member\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable MINIMUM_STAKED_XVS;\n\n /// @notice maximum XVS taken in account when calculating user score\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable MAXIMUM_XVS_CAP;\n\n /// @notice number of days user need to stake to claim prime token\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable\n uint256 public immutable STAKING_PERIOD;\n\n /// @notice Emitted when prime token is minted\n event Mint(address indexed user, bool isIrrevocable);\n\n /// @notice Emitted when prime token is burned\n event Burn(address indexed user);\n\n /// @notice Emitted when a market is added to prime program\n event MarketAdded(\n address indexed comptroller,\n address indexed market,\n uint256 supplyMultiplier,\n uint256 borrowMultiplier\n );\n\n /// @notice Emitted when mint limits are updated\n event MintLimitsUpdated(\n uint256 indexed oldIrrevocableLimit,\n uint256 indexed oldRevocableLimit,\n uint256 indexed newIrrevocableLimit,\n uint256 newRevocableLimit\n );\n\n /// @notice Emitted when user score is updated\n event UserScoreUpdated(address indexed user);\n\n /// @notice Emitted when alpha is updated\n event AlphaUpdated(\n uint128 indexed oldNumerator,\n uint128 indexed oldDenominator,\n uint128 indexed newNumerator,\n uint128 newDenominator\n );\n\n /// @notice Emitted when multiplier is updated\n event MultiplierUpdated(\n address indexed market,\n uint256 indexed oldSupplyMultiplier,\n uint256 indexed oldBorrowMultiplier,\n uint256 newSupplyMultiplier,\n uint256 newBorrowMultiplier\n );\n\n /// @notice Emitted when interest is claimed\n event InterestClaimed(address indexed user, address indexed market, uint256 amount);\n\n /// @notice Emitted when revocable token is upgraded to irrevocable token\n event TokenUpgraded(address indexed user);\n\n /// @notice Emitted when stakedAt is updated\n event StakedAtUpdated(address indexed user, uint256 timestamp);\n\n /// @notice Error thrown when market is not supported\n error MarketNotSupported();\n\n /// @notice Error thrown when mint limit is reached\n error InvalidLimit();\n\n /// @notice Error thrown when user is not eligible to claim prime token\n error IneligibleToClaim();\n\n /// @notice Error thrown when user needs to wait more time to claim prime token\n error WaitMoreTime();\n\n /// @notice Error thrown when user has no prime token\n error UserHasNoPrimeToken();\n\n /// @notice Error thrown when no score updates are required\n error NoScoreUpdatesRequired();\n\n /// @notice Error thrown when market already exists\n error MarketAlreadyExists();\n\n /// @notice Error thrown when asset already exists\n error AssetAlreadyExists();\n\n /// @notice Error thrown when invalid address is passed\n error InvalidAddress();\n\n /// @notice Error thrown when invalid alpha arguments are passed\n error InvalidAlphaArguments();\n\n /// @notice Error thrown when invalid vToken is passed\n error InvalidVToken();\n\n /// @notice Error thrown when invalid length is passed\n error InvalidLength();\n\n /// @notice Error thrown when timestamp is invalid\n error InvalidTimestamp();\n\n /// @notice Error thrown when invalid comptroller is passed\n error InvalidComptroller();\n\n /**\n * @notice Prime constructor\n * @param _wrappedNativeToken Address of wrapped native token\n * @param _nativeMarket Address of native market\n * @param _blocksPerYear total blocks per year\n * @param _stakingPeriod total number of seconds for which user needs to stake to claim prime token\n * @param _minimumStakedXVS minimum amount of XVS user needs to stake to become a prime member (scaled by 1e18)\n * @param _maximumXVSCap maximum XVS taken in account when calculating user score (scaled by 1e18)\n * @param _timeBased A boolean indicating whether the contract is based on time or block.\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(\n address _wrappedNativeToken,\n address _nativeMarket,\n uint256 _blocksPerYear,\n uint256 _stakingPeriod,\n uint256 _minimumStakedXVS,\n uint256 _maximumXVSCap,\n bool _timeBased\n ) TimeManagerV8(_timeBased, _blocksPerYear) {\n WRAPPED_NATIVE_TOKEN = _wrappedNativeToken;\n NATIVE_MARKET = _nativeMarket;\n STAKING_PERIOD = _stakingPeriod;\n MINIMUM_STAKED_XVS = _minimumStakedXVS;\n MAXIMUM_XVS_CAP = _maximumXVSCap;\n\n // Note that the contract is upgradeable. Use initialize() or reinitializers\n // to set the state variables.\n _disableInitializers();\n }\n\n /**\n * @notice Prime initializer\n * @param xvsVault_ Address of XVSVault\n * @param xvsVaultRewardToken_ Address of XVSVault reward token\n * @param xvsVaultPoolId_ Pool id of XVSVault\n * @param alphaNumerator_ numerator of alpha. If alpha is 0.5 then numerator is 1.\n alphaDenominator_ must be greater than alphaNumerator_, alphaDenominator_ cannot be zero and alphaNumerator_ cannot be zero\n * @param alphaDenominator_ denominator of alpha. If alpha is 0.5 then denominator is 2.\n alpha is alphaNumerator_/alphaDenominator_. So, 0 < alpha < 1\n * @param accessControlManager_ Address of AccessControlManager\n * @param primeLiquidityProvider_ Address of PrimeLiquidityProvider\n * @param comptroller_ Address of core pool comptroller\n * @param oracle_ Address of Oracle\n * @param loopsLimit_ Maximum number of loops allowed in a single transaction\n * @custom:error Throw InvalidAddress if any of the address is invalid\n */\n function initialize(\n address xvsVault_,\n address xvsVaultRewardToken_,\n uint256 xvsVaultPoolId_,\n uint128 alphaNumerator_,\n uint128 alphaDenominator_,\n address accessControlManager_,\n address primeLiquidityProvider_,\n address comptroller_,\n address oracle_,\n uint256 loopsLimit_\n ) external initializer {\n if (xvsVault_ == address(0)) revert InvalidAddress();\n if (xvsVaultRewardToken_ == address(0)) revert InvalidAddress();\n if (oracle_ == address(0)) revert InvalidAddress();\n if (primeLiquidityProvider_ == address(0)) revert InvalidAddress();\n\n _checkAlphaArguments(alphaNumerator_, alphaDenominator_);\n\n alphaNumerator = alphaNumerator_;\n alphaDenominator = alphaDenominator_;\n xvsVaultRewardToken = xvsVaultRewardToken_;\n xvsVaultPoolId = xvsVaultPoolId_;\n xvsVault = xvsVault_;\n nextScoreUpdateRoundId = 0;\n primeLiquidityProvider = primeLiquidityProvider_;\n corePoolComptroller = comptroller_;\n oracle = ResilientOracleInterface(oracle_);\n\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n _setMaxLoopsLimit(loopsLimit_);\n\n _pause();\n }\n\n /**\n * @notice Prime initializer V2 for initializing pool registry\n * @param poolRegistry_ Address of IL pool registry\n */\n function initializeV2(address poolRegistry_) external reinitializer(2) {\n poolRegistry = poolRegistry_;\n }\n\n /**\n * @notice Returns boosted pending interest accrued for a user for all markets\n * @param user the account for which to get the accrued interests\n * @return pendingRewards the number of underlying tokens accrued by the user for all markets\n */\n function getPendingRewards(address user) external returns (PendingReward[] memory pendingRewards) {\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n pendingRewards = new PendingReward[](marketsLength);\n for (uint256 i; i < marketsLength; ) {\n address market = allMarkets[i];\n uint256 interestAccrued = getInterestAccrued(market, user);\n uint256 accrued = interests[market][user].accrued;\n\n pendingRewards[i] = PendingReward({\n vToken: market,\n rewardToken: _getUnderlying(market),\n amount: interestAccrued + accrued\n });\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Update total score of multiple users and market\n * @param users accounts for which we need to update score\n * @custom:error Throw NoScoreUpdatesRequired if no score updates are required\n * @custom:error Throw UserHasNoPrimeToken if user has no prime token\n * @custom:event Emits UserScoreUpdated event\n */\n function updateScores(address[] calldata users) external {\n if (pendingScoreUpdates == 0) revert NoScoreUpdatesRequired();\n if (nextScoreUpdateRoundId == 0) revert NoScoreUpdatesRequired();\n\n for (uint256 i; i < users.length; ) {\n address user = users[i];\n\n if (!tokens[user].exists) revert UserHasNoPrimeToken();\n if (isScoreUpdated[nextScoreUpdateRoundId][user]) {\n unchecked {\n ++i;\n }\n continue;\n }\n\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n for (uint256 j; j < marketsLength; ) {\n address market = allMarkets[j];\n _executeBoost(user, market);\n _updateScore(user, market);\n\n unchecked {\n ++j;\n }\n }\n\n --pendingScoreUpdates;\n isScoreUpdated[nextScoreUpdateRoundId][user] = true;\n\n unchecked {\n ++i;\n }\n\n emit UserScoreUpdated(user);\n }\n }\n\n /**\n * @notice Update value of alpha\n * @param _alphaNumerator numerator of alpha. If alpha is 0.5 then numerator is 1\n * @param _alphaDenominator denominator of alpha. If alpha is 0.5 then denominator is 2\n * @custom:event Emits AlphaUpdated event\n * @custom:access Controlled by ACM\n */\n function updateAlpha(uint128 _alphaNumerator, uint128 _alphaDenominator) external {\n _checkAccessAllowed(\"updateAlpha(uint128,uint128)\");\n _checkAlphaArguments(_alphaNumerator, _alphaDenominator);\n\n emit AlphaUpdated(alphaNumerator, alphaDenominator, _alphaNumerator, _alphaDenominator);\n\n alphaNumerator = _alphaNumerator;\n alphaDenominator = _alphaDenominator;\n\n uint256 marketslength = _allMarkets.length;\n\n for (uint256 i; i < marketslength; ) {\n accrueInterest(_allMarkets[i]);\n\n unchecked {\n ++i;\n }\n }\n\n _startScoreUpdateRound();\n }\n\n /**\n * @notice Update multipliers for a market\n * @param market address of the market vToken\n * @param supplyMultiplier new supply multiplier for the market, scaled by 1e18\n * @param borrowMultiplier new borrow multiplier for the market, scaled by 1e18\n * @custom:error Throw MarketNotSupported if market is not supported\n * @custom:event Emits MultiplierUpdated event\n * @custom:access Controlled by ACM\n */\n function updateMultipliers(address market, uint256 supplyMultiplier, uint256 borrowMultiplier) external {\n _checkAccessAllowed(\"updateMultipliers(address,uint256,uint256)\");\n\n Market storage _market = markets[market];\n if (!_market.exists) revert MarketNotSupported();\n\n accrueInterest(market);\n\n emit MultiplierUpdated(\n market,\n _market.supplyMultiplier,\n _market.borrowMultiplier,\n supplyMultiplier,\n borrowMultiplier\n );\n _market.supplyMultiplier = supplyMultiplier;\n _market.borrowMultiplier = borrowMultiplier;\n\n _startScoreUpdateRound();\n }\n\n /**\n * @notice Update staked at timestamp for multiple users\n * @param users accounts for which we need to update staked at timestamp\n * @param timestamps new staked at timestamp for the users\n * @custom:error Throw InvalidLength if users and timestamps length are not equal\n * @custom:event Emits StakedAtUpdated event for each user\n * @custom:access Controlled by ACM\n */\n function setStakedAt(address[] calldata users, uint256[] calldata timestamps) external {\n _checkAccessAllowed(\"setStakedAt(address[],uint256[])\");\n if (users.length != timestamps.length) revert InvalidLength();\n\n for (uint256 i; i < users.length; ) {\n if (timestamps[i] > block.timestamp) revert InvalidTimestamp();\n\n stakedAt[users[i]] = timestamps[i];\n emit StakedAtUpdated(users[i], timestamps[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Add a market to prime program\n * @param comptroller address of the comptroller\n * @param market address of the market vToken\n * @param supplyMultiplier the multiplier for supply cap. It should be converted to 1e18\n * @param borrowMultiplier the multiplier for borrow cap. It should be converted to 1e18\n * @custom:error Throw MarketAlreadyExists if market already exists\n * @custom:error Throw InvalidVToken if market is not valid\n * @custom:event Emits MarketAdded event\n * @custom:access Controlled by ACM\n */\n function addMarket(\n address comptroller,\n address market,\n uint256 supplyMultiplier,\n uint256 borrowMultiplier\n ) external {\n _checkAccessAllowed(\"addMarket(address,address,uint256,uint256)\");\n\n if (comptroller == address(0)) revert InvalidComptroller();\n\n if (\n comptroller != corePoolComptroller &&\n PoolRegistryInterface(poolRegistry).getPoolByComptroller(comptroller).comptroller != comptroller\n ) revert InvalidComptroller();\n\n Market storage _market = markets[market];\n if (_market.exists) revert MarketAlreadyExists();\n\n bool isMarketExist = InterfaceComptroller(comptroller).markets(market);\n if (!isMarketExist) revert InvalidVToken();\n\n delete _market.rewardIndex;\n _market.supplyMultiplier = supplyMultiplier;\n _market.borrowMultiplier = borrowMultiplier;\n delete _market.sumOfMembersScore;\n _market.exists = true;\n\n address underlying = _getUnderlying(market);\n\n if (vTokenForAsset[underlying] != address(0)) revert AssetAlreadyExists();\n vTokenForAsset[underlying] = market;\n\n _allMarkets.push(market);\n _startScoreUpdateRound();\n\n _ensureMaxLoops(_allMarkets.length);\n\n emit MarketAdded(comptroller, market, supplyMultiplier, borrowMultiplier);\n }\n\n /**\n * @notice Set limits for total tokens that can be minted\n * @param _irrevocableLimit total number of irrevocable tokens that can be minted\n * @param _revocableLimit total number of revocable tokens that can be minted\n * @custom:error Throw InvalidLimit if any of the limit is less than total tokens minted\n * @custom:event Emits MintLimitsUpdated event\n * @custom:access Controlled by ACM\n */\n function setLimit(uint256 _irrevocableLimit, uint256 _revocableLimit) external {\n _checkAccessAllowed(\"setLimit(uint256,uint256)\");\n if (_irrevocableLimit < totalIrrevocable || _revocableLimit < totalRevocable) revert InvalidLimit();\n\n emit MintLimitsUpdated(irrevocableLimit, revocableLimit, _irrevocableLimit, _revocableLimit);\n\n revocableLimit = _revocableLimit;\n irrevocableLimit = _irrevocableLimit;\n }\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param loopsLimit Number of loops limit\n * @custom:event Emits MaxLoopsLimitUpdated event on success\n * @custom:access Controlled by ACM\n */\n function setMaxLoopsLimit(uint256 loopsLimit) external {\n _checkAccessAllowed(\"setMaxLoopsLimit(uint256)\");\n _setMaxLoopsLimit(loopsLimit);\n }\n\n /**\n * @notice Directly issue prime tokens to users\n * @param isIrrevocable are the tokens being issued\n * @param users list of address to issue tokens to\n * @custom:access Controlled by ACM\n */\n function issue(bool isIrrevocable, address[] calldata users) external {\n _checkAccessAllowed(\"issue(bool,address[])\");\n\n if (isIrrevocable) {\n for (uint256 i; i < users.length; ) {\n Token storage userToken = tokens[users[i]];\n if (userToken.exists && !userToken.isIrrevocable) {\n _upgrade(users[i]);\n } else {\n _mint(true, users[i]);\n _initializeMarkets(users[i]);\n }\n\n unchecked {\n ++i;\n }\n }\n } else {\n for (uint256 i; i < users.length; ) {\n _mint(false, users[i]);\n _initializeMarkets(users[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n }\n\n /**\n * @notice Executed by XVSVault whenever user's XVSVault balance changes\n * @param user the account address whose balance was updated\n */\n function xvsUpdated(address user) external {\n uint256 totalStaked = _xvsBalanceOfUser(user);\n bool isAccountEligible = _isEligible(totalStaked);\n\n uint256 userStakedAt = stakedAt[user];\n Token memory token = tokens[user];\n\n if (token.exists && !isAccountEligible) {\n delete stakedAt[user];\n emit StakedAtUpdated(user, 0);\n\n if (token.isIrrevocable) {\n _accrueInterestAndUpdateScore(user);\n } else {\n _burn(user);\n }\n } else if (!isAccountEligible && !token.exists && userStakedAt != 0) {\n delete stakedAt[user];\n emit StakedAtUpdated(user, 0);\n } else if (userStakedAt == 0 && isAccountEligible && !token.exists) {\n stakedAt[user] = block.timestamp;\n emit StakedAtUpdated(user, block.timestamp);\n } else if (token.exists && isAccountEligible) {\n _accrueInterestAndUpdateScore(user);\n\n if (stakedAt[user] == 0) {\n stakedAt[user] = block.timestamp;\n emit StakedAtUpdated(user, block.timestamp);\n }\n }\n }\n\n /**\n * @notice accrues interes and updates score for an user for a specific market\n * @param user the account address for which to accrue interest and update score\n * @param market the market for which to accrue interest and update score\n */\n function accrueInterestAndUpdateScore(address user, address market) external {\n _executeBoost(user, market);\n _updateScore(user, market);\n }\n\n /**\n * @notice For claiming prime token when staking period is completed\n */\n function claim() external {\n uint256 userStakedAt = stakedAt[msg.sender];\n if (userStakedAt == 0) revert IneligibleToClaim();\n if (block.timestamp - userStakedAt < STAKING_PERIOD) revert WaitMoreTime();\n\n _mint(false, msg.sender);\n _initializeMarkets(msg.sender);\n }\n\n /**\n * @notice For burning any prime token\n * @param user the account address for which the prime token will be burned\n * @custom:access Controlled by ACM\n */\n function burn(address user) external {\n _checkAccessAllowed(\"burn(address)\");\n _burn(user);\n }\n\n /**\n * @notice To pause or unpause claiming of interest\n * @custom:access Controlled by ACM\n */\n function togglePause() external {\n _checkAccessAllowed(\"togglePause()\");\n if (paused()) {\n _unpause();\n } else {\n _pause();\n }\n }\n\n /**\n * @notice For user to claim boosted yield\n * @param vToken the market for which claim the accrued interest\n * @return amount the amount of tokens transferred to the msg.sender\n */\n function claimInterest(address vToken) external whenNotPaused returns (uint256) {\n return _claimInterest(vToken, msg.sender);\n }\n\n /**\n * @notice For user to claim boosted yield\n * @param vToken the market for which claim the accrued interest\n * @param user the user for which to claim the accrued interest\n * @return amount the amount of tokens transferred to the user\n */\n function claimInterest(address vToken, address user) external whenNotPaused returns (uint256) {\n return _claimInterest(vToken, user);\n }\n\n /**\n * @notice Retrieves an array of all available markets\n * @return an array of addresses representing all available markets\n */\n function getAllMarkets() external view returns (address[] memory) {\n return _allMarkets;\n }\n\n /**\n * @notice Retrieves the core pool comptroller address\n * @return the core pool comptroller address\n */\n function comptroller() external view returns (address) {\n return corePoolComptroller;\n }\n\n /**\n * @notice fetch the numbers of seconds remaining for staking period to complete\n * @param user the account address for which we are checking the remaining time\n * @return timeRemaining the number of seconds the user needs to wait to claim prime token\n */\n function claimTimeRemaining(address user) external view returns (uint256) {\n uint256 userStakedAt = stakedAt[user];\n if (userStakedAt == 0) return STAKING_PERIOD;\n\n uint256 totalTimeStaked;\n unchecked {\n totalTimeStaked = block.timestamp - userStakedAt;\n }\n\n if (totalTimeStaked < STAKING_PERIOD) {\n unchecked {\n return STAKING_PERIOD - totalTimeStaked;\n }\n }\n return 0;\n }\n\n /**\n * @notice Returns if user is a prime holder\n * @return isPrimeHolder true if user is a prime holder\n */\n function isUserPrimeHolder(address user) external view returns (bool) {\n return tokens[user].exists;\n }\n\n /**\n * @notice Returns supply and borrow APR for user for a given market\n * @param market the market for which to fetch the APR\n * @param user the account for which to get the APR\n * @return aprInfo APR information for the user for the given market\n */\n function calculateAPR(address market, address user) external view returns (APRInfo memory aprInfo) {\n IVToken vToken = IVToken(market);\n uint256 borrow = vToken.borrowBalanceStored(user);\n uint256 exchangeRate = vToken.exchangeRateStored();\n uint256 balanceOfAccount = vToken.balanceOf(user);\n uint256 supply = (exchangeRate * balanceOfAccount) / EXP_SCALE;\n\n aprInfo.userScore = interests[market][user].score;\n aprInfo.totalScore = markets[market].sumOfMembersScore;\n\n aprInfo.xvsBalanceForScore = _xvsBalanceForScore(_xvsBalanceOfUser(user));\n Capital memory capital = _capitalForScore(aprInfo.xvsBalanceForScore, borrow, supply, address(vToken));\n\n aprInfo.capital = capital.capital;\n aprInfo.cappedSupply = capital.cappedSupply;\n aprInfo.cappedBorrow = capital.cappedBorrow;\n aprInfo.supplyCapUSD = capital.supplyCapUSD;\n aprInfo.borrowCapUSD = capital.borrowCapUSD;\n\n (aprInfo.supplyAPR, aprInfo.borrowAPR) = _calculateUserAPR(\n market,\n supply,\n borrow,\n aprInfo.cappedSupply,\n aprInfo.cappedBorrow,\n aprInfo.userScore,\n aprInfo.totalScore\n );\n }\n\n /**\n * @notice Returns supply and borrow APR for estimated supply, borrow and XVS staked\n * @param market the market for which to fetch the APR\n * @param user the account for which to get the APR\n * @return aprInfo APR information for the user for the given market\n */\n function estimateAPR(\n address market,\n address user,\n uint256 borrow,\n uint256 supply,\n uint256 xvsStaked\n ) external view returns (APRInfo memory aprInfo) {\n aprInfo.totalScore = markets[market].sumOfMembersScore - interests[market][user].score;\n\n aprInfo.xvsBalanceForScore = _xvsBalanceForScore(xvsStaked);\n Capital memory capital = _capitalForScore(aprInfo.xvsBalanceForScore, borrow, supply, market);\n\n aprInfo.capital = capital.capital;\n aprInfo.cappedSupply = capital.cappedSupply;\n aprInfo.cappedBorrow = capital.cappedBorrow;\n aprInfo.supplyCapUSD = capital.supplyCapUSD;\n aprInfo.borrowCapUSD = capital.borrowCapUSD;\n\n uint256 decimals = IERC20MetadataUpgradeable(_getUnderlying(market)).decimals();\n aprInfo.capital = aprInfo.capital * (10 ** (18 - decimals));\n\n aprInfo.userScore = Scores._calculateScore(\n aprInfo.xvsBalanceForScore,\n aprInfo.capital,\n alphaNumerator,\n alphaDenominator\n );\n\n aprInfo.totalScore = aprInfo.totalScore + aprInfo.userScore;\n\n (aprInfo.supplyAPR, aprInfo.borrowAPR) = _calculateUserAPR(\n market,\n supply,\n borrow,\n aprInfo.cappedSupply,\n aprInfo.cappedBorrow,\n aprInfo.userScore,\n aprInfo.totalScore\n );\n }\n\n /**\n * @notice Distributes income from market since last distribution\n * @param vToken the market for which to distribute the income\n * @custom:error Throw MarketNotSupported if market is not supported\n */\n function accrueInterest(address vToken) public {\n Market storage market = markets[vToken];\n\n if (!market.exists) revert MarketNotSupported();\n\n address underlying = _getUnderlying(vToken);\n\n IPrimeLiquidityProvider _primeLiquidityProvider = IPrimeLiquidityProvider(primeLiquidityProvider);\n _primeLiquidityProvider.accrueTokens(underlying);\n uint256 totalAccruedInPLP = _primeLiquidityProvider.tokenAmountAccrued(underlying);\n uint256 unreleasedPLPAccruedInterest = totalAccruedInPLP - unreleasedPLPIncome[underlying];\n uint256 distributionIncome = unreleasedPLPAccruedInterest;\n\n if (distributionIncome == 0) {\n return;\n }\n\n unreleasedPLPIncome[underlying] = totalAccruedInPLP;\n\n uint256 delta;\n if (market.sumOfMembersScore != 0) {\n delta = ((distributionIncome * EXP_SCALE) / market.sumOfMembersScore);\n }\n\n market.rewardIndex += delta;\n }\n\n /**\n * @notice Returns boosted interest accrued for a user\n * @param vToken the market for which to fetch the accrued interest\n * @param user the account for which to get the accrued interest\n * @return interestAccrued the number of underlying tokens accrued by the user since the last accrual\n */\n function getInterestAccrued(address vToken, address user) public returns (uint256) {\n accrueInterest(vToken);\n\n return _interestAccrued(vToken, user);\n }\n\n /**\n * @notice accrues interest and updates score of all markets for an user\n * @param user the account address for which to accrue interest and update score\n */\n function _accrueInterestAndUpdateScore(address user) internal {\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n for (uint256 i; i < marketsLength; ) {\n address market = allMarkets[i];\n _executeBoost(user, market);\n _updateScore(user, market);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Initializes all the markets for the user when a prime token is minted\n * @param account the account address for which markets needs to be initialized\n */\n function _initializeMarkets(address account) internal {\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n for (uint256 i; i < marketsLength; ) {\n address market = allMarkets[i];\n accrueInterest(market);\n\n interests[market][account].rewardIndex = markets[market].rewardIndex;\n\n uint256 score = _calculateScore(market, account);\n interests[market][account].score = score;\n markets[market].sumOfMembersScore = markets[market].sumOfMembersScore + score;\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice calculate the current score of user\n * @param market the market for which to calculate the score\n * @param user the account for which to calculate the score\n * @return score the score of the user\n */\n function _calculateScore(address market, address user) internal returns (uint256) {\n uint256 xvsBalanceForScore = _xvsBalanceForScore(_xvsBalanceOfUser(user));\n\n IVToken vToken = IVToken(market);\n uint256 borrow = vToken.borrowBalanceStored(user);\n uint256 exchangeRate = vToken.exchangeRateStored();\n uint256 balanceOfAccount = vToken.balanceOf(user);\n uint256 supply = (exchangeRate * balanceOfAccount) / EXP_SCALE;\n\n address xvsToken = IXVSVault(xvsVault).xvsAddress();\n oracle.updateAssetPrice(xvsToken);\n oracle.updatePrice(market);\n\n Capital memory capital = _capitalForScore(xvsBalanceForScore, borrow, supply, market);\n\n uint256 decimals = IERC20MetadataUpgradeable(_getUnderlying(market)).decimals();\n\n capital.capital = capital.capital * (10 ** (18 - decimals));\n\n return Scores._calculateScore(xvsBalanceForScore, capital.capital, alphaNumerator, alphaDenominator);\n }\n\n /**\n * @notice To transfer the accrued interest to user\n * @param vToken the market for which to claim\n * @param user the account for which to get the accrued interest\n * @return amount the amount of tokens transferred to the user\n * @custom:event Emits InterestClaimed event\n */\n function _claimInterest(address vToken, address user) internal returns (uint256) {\n uint256 amount = getInterestAccrued(vToken, user);\n amount += interests[vToken][user].accrued;\n\n interests[vToken][user].rewardIndex = markets[vToken].rewardIndex;\n delete interests[vToken][user].accrued;\n\n address underlying = _getUnderlying(vToken);\n IERC20Upgradeable asset = IERC20Upgradeable(underlying);\n\n if (amount > asset.balanceOf(address(this))) {\n delete unreleasedPLPIncome[underlying];\n IPrimeLiquidityProvider(primeLiquidityProvider).releaseFunds(address(asset));\n }\n\n asset.safeTransfer(user, amount);\n\n emit InterestClaimed(user, vToken, amount);\n\n return amount;\n }\n\n /**\n * @notice Used to mint a new prime token\n * @param isIrrevocable is the tokens being issued is irrevocable\n * @param user token owner\n * @custom:error Throw IneligibleToClaim if user is not eligible to claim prime token\n * @custom:event Emits Mint event\n */\n function _mint(bool isIrrevocable, address user) internal {\n Token storage token = tokens[user];\n if (token.exists) revert IneligibleToClaim();\n\n token.exists = true;\n token.isIrrevocable = isIrrevocable;\n\n if (isIrrevocable) {\n ++totalIrrevocable;\n } else {\n ++totalRevocable;\n }\n\n if (totalIrrevocable > irrevocableLimit || totalRevocable > revocableLimit) revert InvalidLimit();\n _updateRoundAfterTokenMinted(user);\n\n emit Mint(user, isIrrevocable);\n }\n\n /**\n * @notice Used to burn a new prime token\n * @param user owner whose prime token to burn\n * @custom:error Throw UserHasNoPrimeToken if user has no prime token\n * @custom:event Emits Burn event\n */\n function _burn(address user) internal {\n Token memory token = tokens[user];\n if (!token.exists) revert UserHasNoPrimeToken();\n\n address[] storage allMarkets = _allMarkets;\n uint256 marketsLength = allMarkets.length;\n\n for (uint256 i; i < marketsLength; ) {\n address market = allMarkets[i];\n _executeBoost(user, market);\n markets[market].sumOfMembersScore = markets[market].sumOfMembersScore - interests[market][user].score;\n\n delete interests[market][user].score;\n delete interests[market][user].rewardIndex;\n\n unchecked {\n ++i;\n }\n }\n\n if (token.isIrrevocable) {\n --totalIrrevocable;\n } else {\n --totalRevocable;\n }\n\n delete tokens[user].exists;\n delete tokens[user].isIrrevocable;\n\n _updateRoundAfterTokenBurned(user);\n\n emit Burn(user);\n }\n\n /**\n * @notice Used to upgrade an token\n * @param user owner whose prime token to upgrade\n * @custom:error Throw InvalidLimit if total irrevocable tokens exceeds the limit\n * @custom:event Emits TokenUpgraded event\n */\n function _upgrade(address user) internal {\n Token storage userToken = tokens[user];\n\n userToken.isIrrevocable = true;\n ++totalIrrevocable;\n --totalRevocable;\n\n if (totalIrrevocable > irrevocableLimit) revert InvalidLimit();\n\n emit TokenUpgraded(user);\n }\n\n /**\n * @notice Accrue rewards for the user. Must be called before updating score\n * @param user account for which we need to accrue rewards\n * @param vToken the market for which we need to accrue rewards\n */\n function _executeBoost(address user, address vToken) internal {\n if (!markets[vToken].exists || !tokens[user].exists) {\n return;\n }\n\n accrueInterest(vToken);\n interests[vToken][user].accrued += _interestAccrued(vToken, user);\n interests[vToken][user].rewardIndex = markets[vToken].rewardIndex;\n }\n\n /**\n * @notice Update total score of user and market. Must be called after changing account's borrow or supply balance.\n * @param user account for which we need to update score\n * @param market the market for which we need to score\n */\n function _updateScore(address user, address market) internal {\n Market storage _market = markets[market];\n if (!_market.exists || !tokens[user].exists) {\n return;\n }\n\n uint256 score = _calculateScore(market, user);\n _market.sumOfMembersScore = _market.sumOfMembersScore - interests[market][user].score + score;\n\n interests[market][user].score = score;\n }\n\n /**\n * @notice Verify new alpha arguments\n * @param _alphaNumerator numerator of alpha. If alpha is 0.5 then numerator is 1\n * @param _alphaDenominator denominator of alpha. If alpha is 0.5 then denominator is 2\n * @custom:error Throw InvalidAlphaArguments if alpha is invalid\n */\n function _checkAlphaArguments(uint128 _alphaNumerator, uint128 _alphaDenominator) internal pure {\n if (_alphaNumerator >= _alphaDenominator || _alphaNumerator == 0) {\n revert InvalidAlphaArguments();\n }\n }\n\n /**\n * @notice starts round to update scores of a particular or all markets\n */\n function _startScoreUpdateRound() internal {\n nextScoreUpdateRoundId++;\n totalScoreUpdatesRequired = totalIrrevocable + totalRevocable;\n pendingScoreUpdates = totalScoreUpdatesRequired;\n }\n\n /**\n * @notice update the required score updates when token is burned before round is completed\n */\n function _updateRoundAfterTokenBurned(address user) internal {\n if (totalScoreUpdatesRequired != 0) --totalScoreUpdatesRequired;\n\n if (pendingScoreUpdates != 0 && !isScoreUpdated[nextScoreUpdateRoundId][user]) {\n --pendingScoreUpdates;\n }\n }\n\n /**\n * @notice update the required score updates when token is minted before round is completed\n */\n function _updateRoundAfterTokenMinted(address user) internal {\n if (totalScoreUpdatesRequired != 0) isScoreUpdated[nextScoreUpdateRoundId][user] = true;\n }\n\n /**\n * @notice fetch the current XVS balance of user in the XVSVault\n * @param user the account address\n * @return xvsBalance the XVS balance of user\n */\n function _xvsBalanceOfUser(address user) internal view returns (uint256) {\n (uint256 xvs, , uint256 pendingWithdrawals) = IXVSVault(xvsVault).getUserInfo(\n xvsVaultRewardToken,\n xvsVaultPoolId,\n user\n );\n return (xvs - pendingWithdrawals);\n }\n\n /**\n * @notice calculate the current XVS balance that will be used in calculation of score\n * @param xvs the actual XVS balance of user\n * @return xvsBalanceForScore the XVS balance to use in score\n */\n function _xvsBalanceForScore(uint256 xvs) internal view returns (uint256) {\n if (xvs > MAXIMUM_XVS_CAP) {\n return MAXIMUM_XVS_CAP;\n }\n return xvs;\n }\n\n /**\n * @notice calculate the capital for calculation of score\n * @param xvs the actual XVS balance of user\n * @param borrow the borrow balance of user\n * @param supply the supply balance of user\n * @param market the market vToken address\n * @return capital the capital to use in calculation of score\n */\n function _capitalForScore(\n uint256 xvs,\n uint256 borrow,\n uint256 supply,\n address market\n ) internal view returns (Capital memory capital) {\n address xvsToken = IXVSVault(xvsVault).xvsAddress();\n\n uint256 xvsPrice = oracle.getPrice(xvsToken);\n capital.borrowCapUSD = (xvsPrice * ((xvs * markets[market].borrowMultiplier) / EXP_SCALE)) / EXP_SCALE;\n capital.supplyCapUSD = (xvsPrice * ((xvs * markets[market].supplyMultiplier) / EXP_SCALE)) / EXP_SCALE;\n\n uint256 tokenPrice = oracle.getUnderlyingPrice(market);\n uint256 supplyUSD = (tokenPrice * supply) / EXP_SCALE;\n uint256 borrowUSD = (tokenPrice * borrow) / EXP_SCALE;\n\n if (supplyUSD >= capital.supplyCapUSD) {\n supply = supplyUSD != 0 ? (supply * capital.supplyCapUSD) / supplyUSD : 0;\n }\n\n if (borrowUSD >= capital.borrowCapUSD) {\n borrow = borrowUSD != 0 ? (borrow * capital.borrowCapUSD) / borrowUSD : 0;\n }\n\n capital.capital = supply + borrow;\n capital.cappedSupply = supply;\n capital.cappedBorrow = borrow;\n }\n\n /**\n * @notice Used to get if the XVS balance is eligible for prime token\n * @param amount amount of XVS\n * @return isEligible true if the staked XVS amount is enough to consider the associated user eligible for a Prime token, false otherwise\n */\n function _isEligible(uint256 amount) internal view returns (bool) {\n if (amount >= MINIMUM_STAKED_XVS) {\n return true;\n }\n\n return false;\n }\n\n /**\n * @notice Calculate the interests accrued by the user in the market, since the last accrual\n * @param vToken the market for which to calculate the accrued interest\n * @param user the user for which to calculate the accrued interest\n * @return interestAccrued the number of underlying tokens accrued by the user since the last accrual\n */\n function _interestAccrued(address vToken, address user) internal view returns (uint256) {\n Interest memory interest = interests[vToken][user];\n uint256 index = markets[vToken].rewardIndex - interest.rewardIndex;\n\n uint256 score = interest.score;\n\n return (index * score) / EXP_SCALE;\n }\n\n /**\n * @notice Returns the underlying token associated with the VToken, or wrapped native token if the market is native market\n * @param vToken the market whose underlying token will be returned\n * @return underlying The address of the underlying token associated with the VToken, or the address of the WRAPPED_NATIVE_TOKEN token if the market is NATIVE_MARKET\n */\n function _getUnderlying(address vToken) internal view returns (address) {\n if (vToken == NATIVE_MARKET) {\n return WRAPPED_NATIVE_TOKEN;\n }\n return IVToken(vToken).underlying();\n }\n\n //////////////////////////////////////////////////\n //////////////// APR Calculation ////////////////\n ////////////////////////////////////////////////\n\n /**\n * @notice the total income that's going to be distributed in a year to prime token holders\n * @param vToken the market for which to fetch the total income that's going to distributed in a year\n * @return amount the total income\n */\n function incomeDistributionYearly(address vToken) public view returns (uint256 amount) {\n uint256 totalIncomePerBlockOrSecondFromPLP = IPrimeLiquidityProvider(primeLiquidityProvider)\n .getEffectiveDistributionSpeed(_getUnderlying(vToken));\n amount = blocksOrSecondsPerYear * totalIncomePerBlockOrSecondFromPLP;\n }\n\n /**\n * @notice used to calculate the supply and borrow APR of the user\n * @param vToken the market for which to fetch the APR\n * @param totalSupply the total token supply of the user\n * @param totalBorrow the total tokens borrowed by the user\n * @param totalCappedSupply the total token capped supply of the user\n * @param totalCappedBorrow the total capped tokens borrowed by the user\n * @param userScore the score of the user\n * @param totalScore the total market score\n * @return supplyAPR the supply APR of the user\n * @return borrowAPR the borrow APR of the user\n */\n function _calculateUserAPR(\n address vToken,\n uint256 totalSupply,\n uint256 totalBorrow,\n uint256 totalCappedSupply,\n uint256 totalCappedBorrow,\n uint256 userScore,\n uint256 totalScore\n ) internal view returns (uint256 supplyAPR, uint256 borrowAPR) {\n if (totalScore == 0) return (0, 0);\n\n uint256 userYearlyIncome = (userScore * incomeDistributionYearly(vToken)) / totalScore;\n\n uint256 totalCappedValue = totalCappedSupply + totalCappedBorrow;\n\n if (totalCappedValue == 0) return (0, 0);\n\n uint256 maximumBps = MAXIMUM_BPS;\n uint256 userSupplyIncomeYearly;\n uint256 userBorrowIncomeYearly;\n userSupplyIncomeYearly = (userYearlyIncome * totalCappedSupply) / totalCappedValue;\n userBorrowIncomeYearly = (userYearlyIncome * totalCappedBorrow) / totalCappedValue;\n supplyAPR = totalSupply == 0 ? 0 : ((userSupplyIncomeYearly * maximumBps) / totalSupply);\n borrowAPR = totalBorrow == 0 ? 0 : ((userBorrowIncomeYearly * maximumBps) / totalBorrow);\n }\n}\n" + }, + "contracts/Tokens/Prime/PrimeLiquidityProvider.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { PrimeLiquidityProviderStorageV1 } from \"./PrimeLiquidityProviderStorage.sol\";\nimport { SafeERC20Upgradeable, IERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/utils/SafeERC20Upgradeable.sol\";\nimport { AccessControlledV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/AccessControlledV8.sol\";\nimport { PausableUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/PausableUpgradeable.sol\";\nimport { IPrimeLiquidityProvider } from \"./Interfaces/IPrimeLiquidityProvider.sol\";\nimport { MaxLoopsLimitHelper } from \"@venusprotocol/solidity-utilities/contracts/MaxLoopsLimitHelper.sol\";\nimport { TimeManagerV8 } from \"@venusprotocol/solidity-utilities/contracts/TimeManagerV8.sol\";\n\n/**\n * @title PrimeLiquidityProvider\n * @author Venus\n * @notice PrimeLiquidityProvider is used to fund Prime\n */\ncontract PrimeLiquidityProvider is\n IPrimeLiquidityProvider,\n AccessControlledV8,\n PausableUpgradeable,\n MaxLoopsLimitHelper,\n PrimeLiquidityProviderStorageV1,\n TimeManagerV8\n{\n using SafeERC20Upgradeable for IERC20Upgradeable;\n\n /// @notice The default max token distribution speed\n uint256 public constant DEFAULT_MAX_DISTRIBUTION_SPEED = 1e18;\n\n /// @notice Emitted when a token distribution is initialized\n event TokenDistributionInitialized(address indexed token);\n\n /// @notice Emitted when a new token distribution speed is set\n event TokenDistributionSpeedUpdated(address indexed token, uint256 oldSpeed, uint256 newSpeed);\n\n /// @notice Emitted when a new max distribution speed for token is set\n event MaxTokenDistributionSpeedUpdated(address indexed token, uint256 oldSpeed, uint256 newSpeed);\n\n /// @notice Emitted when prime token contract address is changed\n event PrimeTokenUpdated(address indexed oldPrimeToken, address indexed newPrimeToken);\n\n /// @notice Emitted when distribution state(Index and block or second) is updated\n event TokensAccrued(address indexed token, uint256 amount);\n\n /// @notice Emitted when token is transferred to the prime contract\n event TokenTransferredToPrime(address indexed token, uint256 amount);\n\n /// @notice Emitted on sweep token success\n event SweepToken(address indexed token, address indexed to, uint256 sweepAmount);\n\n /// @notice Thrown when arguments are passed are invalid\n error InvalidArguments();\n\n /// @notice Thrown when distribution speed is greater than maxTokenDistributionSpeeds[tokenAddress]\n error InvalidDistributionSpeed(uint256 speed, uint256 maxSpeed);\n\n /// @notice Thrown when caller is not the desired caller\n error InvalidCaller();\n\n /// @notice Thrown when token is initialized\n error TokenAlreadyInitialized(address token);\n\n ///@notice Error thrown when PrimeLiquidityProvider's balance is less than sweep amount\n error InsufficientBalance(uint256 sweepAmount, uint256 balance);\n\n /// @notice Error thrown when funds transfer is paused\n error FundsTransferIsPaused();\n\n /// @notice Error thrown when accrueTokens is called for an uninitialized token\n error TokenNotInitialized(address token_);\n\n /// @notice Error thrown when argument value in setter is same as previous value\n error AddressesMustDiffer();\n\n /**\n * @notice Compares two addresses to ensure they are different\n * @param oldAddress The original address to compare\n * @param newAddress The new address to compare\n */\n modifier compareAddress(address oldAddress, address newAddress) {\n if (newAddress == oldAddress) {\n revert AddressesMustDiffer();\n }\n _;\n }\n\n /**\n * @notice Prime Liquidity Provider constructor\n * @param _timeBased A boolean indicating whether the contract is based on time or block.\n * @param _blocksPerYear total blocks per year\n */\n /// @custom:oz-upgrades-unsafe-allow constructor\n constructor(bool _timeBased, uint256 _blocksPerYear) TimeManagerV8(_timeBased, _blocksPerYear) {\n _disableInitializers();\n }\n\n /**\n * @notice PrimeLiquidityProvider initializer\n * @dev Initializes the deployer to owner\n * @param accessControlManager_ AccessControlManager contract address\n * @param tokens_ Array of addresses of the tokens\n * @param distributionSpeeds_ New distribution speeds for tokens\n * @param loopsLimit_ Maximum number of loops allowed in a single transaction\n * @custom:error Throw InvalidArguments on different length of tokens and speeds array\n */\n function initialize(\n address accessControlManager_,\n address[] calldata tokens_,\n uint256[] calldata distributionSpeeds_,\n uint256[] calldata maxDistributionSpeeds_,\n uint256 loopsLimit_\n ) external initializer {\n _ensureZeroAddress(accessControlManager_);\n\n __AccessControlled_init(accessControlManager_);\n __Pausable_init();\n _setMaxLoopsLimit(loopsLimit_);\n\n uint256 numTokens = tokens_.length;\n _ensureMaxLoops(numTokens);\n\n if ((numTokens != distributionSpeeds_.length) || (numTokens != maxDistributionSpeeds_.length)) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < numTokens; ) {\n _initializeToken(tokens_[i]);\n _setMaxTokenDistributionSpeed(tokens_[i], maxDistributionSpeeds_[i]);\n _setTokenDistributionSpeed(tokens_[i], distributionSpeeds_[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Initialize the distribution of the token\n * @param tokens_ Array of addresses of the tokens to be intialized\n * @custom:access Only Governance\n */\n function initializeTokens(address[] calldata tokens_) external onlyOwner {\n uint256 tokensLength = tokens_.length;\n _ensureMaxLoops(tokensLength);\n\n for (uint256 i; i < tokensLength; ) {\n _initializeToken(tokens_[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Pause fund transfer of tokens to Prime contract\n * @custom:access Controlled by ACM\n */\n function pauseFundsTransfer() external {\n _checkAccessAllowed(\"pauseFundsTransfer()\");\n _pause();\n }\n\n /**\n * @notice Resume fund transfer of tokens to Prime contract\n * @custom:access Controlled by ACM\n */\n function resumeFundsTransfer() external {\n _checkAccessAllowed(\"resumeFundsTransfer()\");\n _unpause();\n }\n\n /**\n * @notice Set distribution speed (amount of token distribute per block or second)\n * @param tokens_ Array of addresses of the tokens\n * @param distributionSpeeds_ New distribution speeds for tokens\n * @custom:access Controlled by ACM\n * @custom:error Throw InvalidArguments on different length of tokens and speeds array\n */\n function setTokensDistributionSpeed(address[] calldata tokens_, uint256[] calldata distributionSpeeds_) external {\n _checkAccessAllowed(\"setTokensDistributionSpeed(address[],uint256[])\");\n uint256 numTokens = tokens_.length;\n _ensureMaxLoops(numTokens);\n\n if (numTokens != distributionSpeeds_.length) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < numTokens; ) {\n _ensureTokenInitialized(tokens_[i]);\n _setTokenDistributionSpeed(tokens_[i], distributionSpeeds_[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set max distribution speed for token (amount of maximum token distribute per block or second)\n * @param tokens_ Array of addresses of the tokens\n * @param maxDistributionSpeeds_ New distribution speeds for tokens\n * @custom:access Controlled by ACM\n * @custom:error Throw InvalidArguments on different length of tokens and speeds array\n */\n function setMaxTokensDistributionSpeed(\n address[] calldata tokens_,\n uint256[] calldata maxDistributionSpeeds_\n ) external {\n _checkAccessAllowed(\"setMaxTokensDistributionSpeed(address[],uint256[])\");\n uint256 numTokens = tokens_.length;\n _ensureMaxLoops(numTokens);\n\n if (numTokens != maxDistributionSpeeds_.length) {\n revert InvalidArguments();\n }\n\n for (uint256 i; i < numTokens; ) {\n _setMaxTokenDistributionSpeed(tokens_[i], maxDistributionSpeeds_[i]);\n\n unchecked {\n ++i;\n }\n }\n }\n\n /**\n * @notice Set the prime token contract address\n * @param prime_ The new address of the prime token contract\n * @custom:event Emits PrimeTokenUpdated event\n * @custom:access Only owner\n */\n function setPrimeToken(address prime_) external onlyOwner compareAddress(prime, prime_) {\n _ensureZeroAddress(prime_);\n\n emit PrimeTokenUpdated(prime, prime_);\n prime = prime_;\n }\n\n /**\n * @notice Set the limit for the loops can iterate to avoid the DOS\n * @param loopsLimit Limit for the max loops can execute at a time\n * @custom:event Emits MaxLoopsLimitUpdated event on success\n * @custom:access Controlled by ACM\n */\n function setMaxLoopsLimit(uint256 loopsLimit) external {\n _checkAccessAllowed(\"setMaxLoopsLimit(uint256)\");\n _setMaxLoopsLimit(loopsLimit);\n }\n\n /**\n * @notice Claim all the token accrued till last block or second\n * @param token_ The token to release to the Prime contract\n * @custom:event Emits TokenTransferredToPrime event\n * @custom:error Throw InvalidArguments on Zero address(token)\n * @custom:error Throw FundsTransferIsPaused is paused\n * @custom:error Throw InvalidCaller if the sender is not the Prime contract\n */\n function releaseFunds(address token_) external {\n address _prime = prime;\n if (msg.sender != _prime) revert InvalidCaller();\n if (paused()) {\n revert FundsTransferIsPaused();\n }\n\n accrueTokens(token_);\n uint256 accruedAmount = _tokenAmountAccrued[token_];\n delete _tokenAmountAccrued[token_];\n\n emit TokenTransferredToPrime(token_, accruedAmount);\n\n IERC20Upgradeable(token_).safeTransfer(_prime, accruedAmount);\n }\n\n /**\n * @notice A public function to sweep accidental ERC-20 transfers to this contract. Tokens are sent to user\n * @param token_ The address of the ERC-20 token to sweep\n * @param to_ The address of the recipient\n * @param amount_ The amount of tokens needs to transfer\n * @custom:event Emits SweepToken event\n * @custom:error Throw InsufficientBalance if amount_ is greater than the available balance of the token in the contract\n * @custom:access Only Governance\n */\n function sweepToken(IERC20Upgradeable token_, address to_, uint256 amount_) external onlyOwner {\n uint256 balance = token_.balanceOf(address(this));\n if (amount_ > balance) {\n revert InsufficientBalance(amount_, balance);\n }\n\n emit SweepToken(address(token_), to_, amount_);\n\n token_.safeTransfer(to_, amount_);\n }\n\n /**\n * @notice Get rewards per block or second for token\n * @param token_ Address of the token\n * @return speed returns the per block or second reward\n */\n function getEffectiveDistributionSpeed(address token_) external view returns (uint256) {\n uint256 distributionSpeed = tokenDistributionSpeeds[token_];\n uint256 balance = IERC20Upgradeable(token_).balanceOf(address(this));\n uint256 accrued = _tokenAmountAccrued[token_];\n\n if (balance > accrued) {\n return distributionSpeed;\n }\n\n return 0;\n }\n\n /**\n * @notice Accrue token by updating the distribution state\n * @param token_ Address of the token\n * @custom:event Emits TokensAccrued event\n */\n function accrueTokens(address token_) public {\n _ensureZeroAddress(token_);\n\n _ensureTokenInitialized(token_);\n\n uint256 blockNumberOrSecond = getBlockNumberOrTimestamp();\n uint256 deltaBlocksOrSeconds;\n unchecked {\n deltaBlocksOrSeconds = blockNumberOrSecond - lastAccruedBlockOrSecond[token_];\n }\n\n if (deltaBlocksOrSeconds != 0) {\n uint256 distributionSpeed = tokenDistributionSpeeds[token_];\n uint256 balance = IERC20Upgradeable(token_).balanceOf(address(this));\n\n uint256 balanceDiff = balance - _tokenAmountAccrued[token_];\n if (distributionSpeed != 0 && balanceDiff != 0) {\n uint256 accruedSinceUpdate = deltaBlocksOrSeconds * distributionSpeed;\n uint256 tokenAccrued = (balanceDiff <= accruedSinceUpdate ? balanceDiff : accruedSinceUpdate);\n\n _tokenAmountAccrued[token_] += tokenAccrued;\n emit TokensAccrued(token_, tokenAccrued);\n }\n\n lastAccruedBlockOrSecond[token_] = blockNumberOrSecond;\n }\n }\n\n /**\n * @notice Get the last accrued block or second for token\n * @param token_ Address of the token\n * @return blockNumberOrSecond returns the last accrued block or second\n */\n function lastAccruedBlock(address token_) external view returns (uint256) {\n return lastAccruedBlockOrSecond[token_];\n }\n\n /**\n * @notice Get the tokens accrued\n * @param token_ Address of the token\n * @return returns the amount of accrued tokens for the token provided\n */\n function tokenAmountAccrued(address token_) external view returns (uint256) {\n return _tokenAmountAccrued[token_];\n }\n\n /**\n * @notice Initialize the distribution of the token\n * @param token_ Address of the token to be intialized\n * @custom:event Emits TokenDistributionInitialized event\n * @custom:error Throw TokenAlreadyInitialized if token is already initialized\n */\n function _initializeToken(address token_) internal {\n _ensureZeroAddress(token_);\n uint256 blockNumberOrSecond = getBlockNumberOrTimestamp();\n uint256 initializedBlockOrSecond = lastAccruedBlockOrSecond[token_];\n\n if (initializedBlockOrSecond != 0) {\n revert TokenAlreadyInitialized(token_);\n }\n\n /*\n * Update token state block number or second\n */\n lastAccruedBlockOrSecond[token_] = blockNumberOrSecond;\n\n emit TokenDistributionInitialized(token_);\n }\n\n /**\n * @notice Set distribution speed (amount of token distribute per block or second)\n * @param token_ Address of the token\n * @param distributionSpeed_ New distribution speed for token\n * @custom:event Emits TokenDistributionSpeedUpdated event\n * @custom:error Throw InvalidDistributionSpeed if speed is greater than max speed\n */\n function _setTokenDistributionSpeed(address token_, uint256 distributionSpeed_) internal {\n uint256 maxDistributionSpeed = maxTokenDistributionSpeeds[token_];\n if (maxDistributionSpeed == 0) {\n maxTokenDistributionSpeeds[token_] = maxDistributionSpeed = DEFAULT_MAX_DISTRIBUTION_SPEED;\n }\n\n if (distributionSpeed_ > maxDistributionSpeed) {\n revert InvalidDistributionSpeed(distributionSpeed_, maxDistributionSpeed);\n }\n\n uint256 oldDistributionSpeed = tokenDistributionSpeeds[token_];\n if (oldDistributionSpeed != distributionSpeed_) {\n // Distribution speed updated so let's update distribution state to ensure that\n // 1. Token accrued properly for the old speed, and\n // 2. Token accrued at the new speed starts after this block or second.\n accrueTokens(token_);\n\n // Update speed\n tokenDistributionSpeeds[token_] = distributionSpeed_;\n\n emit TokenDistributionSpeedUpdated(token_, oldDistributionSpeed, distributionSpeed_);\n }\n }\n\n /**\n * @notice Set max distribution speed (amount of maximum token distribute per block or second)\n * @param token_ Address of the token\n * @param maxDistributionSpeed_ New max distribution speed for token\n * @custom:event Emits MaxTokenDistributionSpeedUpdated event\n */\n function _setMaxTokenDistributionSpeed(address token_, uint256 maxDistributionSpeed_) internal {\n emit MaxTokenDistributionSpeedUpdated(token_, tokenDistributionSpeeds[token_], maxDistributionSpeed_);\n maxTokenDistributionSpeeds[token_] = maxDistributionSpeed_;\n }\n\n /**\n * @notice Revert on non initialized token\n * @param token_ Token Address to be verified for\n */\n function _ensureTokenInitialized(address token_) internal view {\n uint256 lastBlockOrSecondAccrued = lastAccruedBlockOrSecond[token_];\n\n if (lastBlockOrSecondAccrued == 0) {\n revert TokenNotInitialized(token_);\n }\n }\n\n /**\n * @notice Revert on zero address\n * @param address_ Address to be verified\n */\n function _ensureZeroAddress(address address_) internal pure {\n if (address_ == address(0)) {\n revert InvalidArguments();\n }\n }\n}\n" + }, + "contracts/Tokens/Prime/PrimeLiquidityProviderStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title PrimeLiquidityProviderStorageV1\n * @author Venus\n * @notice Storage for Prime Liquidity Provider\n */\ncontract PrimeLiquidityProviderStorageV1 {\n /// @notice Address of the Prime contract\n address public prime;\n\n /// @notice The rate at which token is distributed (per block or second)\n mapping(address => uint256) public tokenDistributionSpeeds;\n\n /// @notice The max token distribution speed for token\n mapping(address => uint256) public maxTokenDistributionSpeeds;\n\n /// @notice The block or second till which rewards are distributed for an asset\n mapping(address => uint256) public lastAccruedBlockOrSecond;\n\n /// @notice The token accrued but not yet transferred to prime contract\n mapping(address => uint256) internal _tokenAmountAccrued;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n uint256[45] private __gap;\n}\n" + }, + "contracts/Tokens/Prime/PrimeStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\n\n/**\n * @title PrimeStorageV1\n * @author Venus\n * @notice Storage for Prime Token\n */\ncontract PrimeStorageV1 {\n struct Token {\n bool exists;\n bool isIrrevocable;\n }\n\n struct Market {\n uint256 supplyMultiplier;\n uint256 borrowMultiplier;\n uint256 rewardIndex;\n uint256 sumOfMembersScore;\n bool exists;\n }\n\n struct Interest {\n uint256 accrued;\n uint256 score;\n uint256 rewardIndex;\n }\n\n struct PendingReward {\n address vToken;\n address rewardToken;\n uint256 amount;\n }\n\n /// @notice Base unit for computations, usually used in scaling (multiplications, divisions)\n uint256 internal constant EXP_SCALE = 1e18;\n\n /// @notice maximum BPS = 100%\n uint256 internal constant MAXIMUM_BPS = 1e4;\n\n /// @notice Mapping to get prime token's metadata\n mapping(address => Token) public tokens;\n\n /// @notice Tracks total irrevocable tokens minted\n uint256 public totalIrrevocable;\n\n /// @notice Tracks total revocable tokens minted\n uint256 public totalRevocable;\n\n /// @notice Indicates maximum revocable tokens that can be minted\n uint256 public revocableLimit;\n\n /// @notice Indicates maximum irrevocable tokens that can be minted\n uint256 public irrevocableLimit;\n\n /// @notice Tracks when prime token eligible users started staking for claiming prime token\n mapping(address => uint256) public stakedAt;\n\n /// @notice vToken to market configuration\n mapping(address => Market) public markets;\n\n /// @notice vToken to user to user index\n mapping(address => mapping(address => Interest)) public interests;\n\n /// @notice A list of boosted markets\n address[] internal _allMarkets;\n\n /// @notice numerator of alpha. Ex: if alpha is 0.5 then this will be 1\n uint128 public alphaNumerator;\n\n /// @notice denominator of alpha. Ex: if alpha is 0.5 then this will be 2\n uint128 public alphaDenominator;\n\n /// @notice address of XVS vault\n address public xvsVault;\n\n /// @notice address of XVS vault reward token\n address public xvsVaultRewardToken;\n\n /// @notice address of XVS vault pool id\n uint256 public xvsVaultPoolId;\n\n /// @notice mapping to check if a account's score was updated in the round\n mapping(uint256 => mapping(address => bool)) public isScoreUpdated;\n\n /// @notice unique id for next round\n uint256 public nextScoreUpdateRoundId;\n\n /// @notice total number of accounts whose score needs to be updated\n uint256 public totalScoreUpdatesRequired;\n\n /// @notice total number of accounts whose score is yet to be updated\n uint256 public pendingScoreUpdates;\n\n /// @notice mapping used to find if an asset is part of prime markets\n mapping(address => address) public vTokenForAsset;\n\n /// @notice Address of core pool comptroller contract\n address internal corePoolComptroller;\n\n /// @notice unreleased income from PLP that's already distributed to prime holders\n /// @dev mapping of asset address => amount\n mapping(address => uint256) public unreleasedPLPIncome;\n\n /// @notice The address of PLP contract\n address public primeLiquidityProvider;\n\n /// @notice The address of ResilientOracle contract\n ResilientOracleInterface public oracle;\n\n /// @notice The address of PoolRegistry contract\n address public poolRegistry;\n\n /// @dev This empty reserved space is put in place to allow future versions to add new\n /// variables without shifting down storage in the inheritance chain.\n uint256[26] private __gap;\n}\n" + }, + "contracts/Tokens/test/IERC20NonStandard.sol": { + "content": "pragma solidity 0.8.25;\n\n/**\n * @title EIP20NonStandardInterface\n * @dev Version of BEP20 with no return values for `transfer` and `transferFrom`\n * See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca\n */\ninterface IERC20NonStandard {\n /**\n * @notice Get the total number of tokens in circulation\n * @return The supply of tokens\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @notice Gets the balance of the specified address\n * @param owner The address from which the balance will be retrieved\n * @return balance of the owner\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transfer` does not return a value, in violation of the BEP-20 specification\n /// !!!!!!!!!!!!!!\n ///\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n */\n function transfer(address dst, uint256 amount) external;\n\n ///\n /// !!!!!!!!!!!!!!\n /// !!! NOTICE !!! `transferFrom` does not return a value, in violation of the BEP-20 specification\n /// !!!!!!!!!!!!!!\n ///\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n */\n function transferFrom(address src, address dst, uint256 amount) external;\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved\n * @return success Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external returns (bool success);\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return remaining The number of tokens allowed to be spent\n */\n function allowance(address owner, address spender) external view returns (uint256 remaining);\n\n event Transfer(address indexed from, address indexed to, uint256 amount);\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n}\n" + }, + "contracts/Tokens/VAI/IVAI.sol": { + "content": "// SPDX-License-Identifier: AGPL-3.0-or-later\n// Copyright (C) 2017, 2018, 2019 dbrock, rain, mrchico\n\npragma solidity 0.8.25;\n\ninterface IVAI {\n // --- Auth ---\n function wards(address) external view returns (uint256);\n function rely(address guy) external;\n function deny(address guy) external;\n\n // --- BEP20 Data ---\n function name() external pure returns (string memory);\n function symbol() external pure returns (string memory);\n function version() external pure returns (string memory);\n function decimals() external pure returns (uint8);\n function totalSupply() external view returns (uint256);\n\n function balanceOf(address) external view returns (uint256);\n function allowance(address, address) external view returns (uint256);\n function nonces(address) external view returns (uint256);\n\n event Approval(address indexed src, address indexed guy, uint256 wad);\n event Transfer(address indexed src, address indexed dst, uint256 wad);\n\n // --- EIP712 niceties ---\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n // bytes32 public constant PERMIT_TYPEHASH = keccak256(\"Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)\");\n function PERMIT_TYPEHASH() external pure returns (bytes32);\n\n // --- Token ---\n function transfer(address dst, uint256 wad) external returns (bool);\n function transferFrom(address src, address dst, uint256 wad) external returns (bool);\n function mint(address usr, uint256 wad) external;\n function burn(address usr, uint256 wad) external;\n function approve(address usr, uint256 wad) external returns (bool);\n\n // --- Alias ---\n function push(address usr, uint256 wad) external;\n function pull(address usr, uint256 wad) external;\n function move(address src, address dst, uint256 wad) external;\n\n // --- Approve by signature ---\n function permit(\n address holder,\n address spender,\n uint256 nonce,\n uint256 expiry,\n bool allowed,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n}\n" + }, + "contracts/Tokens/VAI/VAIController.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ResilientOracleInterface } from \"@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol\";\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\nimport { VAIControllerErrorReporter } from \"../../Utils/ErrorReporter.sol\";\nimport { Exponential } from \"../../Utils/Exponential.sol\";\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { VToken } from \"../VTokens/VToken.sol\";\nimport { VAIUnitroller } from \"./VAIUnitroller.sol\";\nimport { VAIControllerInterface } from \"./VAIControllerInterface.sol\";\nimport { IVAI } from \"./IVAI.sol\";\nimport { IPrime } from \"../Prime/IPrime.sol\";\nimport { VTokenInterface } from \"../VTokens/VTokenInterfaces.sol\";\nimport { VAIControllerStorageG4 } from \"./VAIControllerStorage.sol\";\nimport { IDeviationBoundedOracle } from \"@venusprotocol/oracle/contracts/interfaces/IDeviationBoundedOracle.sol\";\n\n/**\n * @title VAI Comptroller\n * @author Venus\n * @notice This is the implementation contract for the VAIUnitroller proxy\n */\ncontract VAIController is VAIControllerInterface, VAIControllerStorageG4, VAIControllerErrorReporter, Exponential {\n /// @notice Initial index used in interest computations\n uint256 public constant INITIAL_VAI_MINT_INDEX = 1e18;\n\n /// poolId for core Pool\n uint96 public constant CORE_POOL_ID = 0;\n\n /// @notice Emitted when Comptroller is changed\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\n\n /// @notice Emitted when mint for prime holder is changed\n event MintOnlyForPrimeHolder(bool previousMintEnabledOnlyForPrimeHolder, bool newMintEnabledOnlyForPrimeHolder);\n\n /// @notice Emitted when Prime is changed\n event NewPrime(address oldPrime, address newPrime);\n\n /// @notice Event emitted when VAI is minted\n event MintVAI(address minter, uint256 mintVAIAmount);\n\n /// @notice Event emitted when VAI is repaid\n event RepayVAI(address payer, address borrower, uint256 repayVAIAmount);\n\n /// @notice Event emitted when a borrow is liquidated\n event LiquidateVAI(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n address vTokenCollateral,\n uint256 seizeTokens\n );\n\n /// @notice Emitted when treasury guardian is changed\n event NewTreasuryGuardian(address oldTreasuryGuardian, address newTreasuryGuardian);\n\n /// @notice Emitted when treasury address is changed\n event NewTreasuryAddress(address oldTreasuryAddress, address newTreasuryAddress);\n\n /// @notice Emitted when treasury percent is changed\n event NewTreasuryPercent(uint256 oldTreasuryPercent, uint256 newTreasuryPercent);\n\n /// @notice Event emitted when VAIs are minted and fee are transferred\n event MintFee(address minter, uint256 feeAmount);\n\n /// @notice Emiitted when VAI base rate is changed\n event NewVAIBaseRate(uint256 oldBaseRateMantissa, uint256 newBaseRateMantissa);\n\n /// @notice Emiitted when VAI float rate is changed\n event NewVAIFloatRate(uint256 oldFloatRateMantissa, uint256 newFlatRateMantissa);\n\n /// @notice Emiitted when VAI receiver address is changed\n event NewVAIReceiver(address oldReceiver, address newReceiver);\n\n /// @notice Emiitted when VAI mint cap is changed\n event NewVAIMintCap(uint256 oldMintCap, uint256 newMintCap);\n\n /// @notice Emitted when access control address is changed by admin\n event NewAccessControl(address oldAccessControlAddress, address newAccessControlAddress);\n\n /// @notice Emitted when VAI token address is changed by admin\n event NewVaiToken(address oldVaiToken, address newVaiToken);\n\n function initialize() external onlyAdmin {\n require(vaiMintIndex == 0, \"already initialized\");\n\n vaiMintIndex = INITIAL_VAI_MINT_INDEX;\n accrualBlockNumber = getBlockNumber();\n mintCap = type(uint256).max;\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n }\n\n function _become(VAIUnitroller unitroller) external {\n require(msg.sender == unitroller.admin(), \"only unitroller admin can change brains\");\n require(unitroller._acceptImplementation() == 0, \"change not authorized\");\n }\n\n /**\n * @notice The mintVAI function mints and transfers VAI from the protocol to the user, and adds a borrow balance.\n * The amount minted must be less than the user's Account Liquidity and the mint vai limit.\n * @dev If the Comptroller address is not set, minting is a no-op and the function returns the success code.\n * @param mintVAIAmount The amount of the VAI to be minted.\n * @return 0 on success, otherwise an error code\n */\n // solhint-disable-next-line code-complexity\n function mintVAI(uint256 mintVAIAmount) external nonReentrant returns (uint256) {\n if (address(comptroller) == address(0)) {\n return uint256(Error.NO_ERROR);\n }\n\n require(comptroller.userPoolId(msg.sender) == CORE_POOL_ID, \"VAI mint only allowed in the core Pool\");\n\n _ensureNonzeroAmount(mintVAIAmount);\n _ensureNotPaused();\n accrueVAIInterest();\n\n uint256 err;\n address minter = msg.sender;\n address _vai = vai;\n uint256 vaiTotalSupply = IVAI(_vai).totalSupply();\n\n uint256 vaiNewTotalSupply = add_(vaiTotalSupply, mintVAIAmount);\n require(vaiNewTotalSupply <= mintCap, \"mint cap reached\");\n\n _updateProtectionStateForEnteredMarkets(minter);\n\n uint256 accountMintableVAI;\n (err, accountMintableVAI) = getMintableVAI(minter);\n require(err == uint256(Error.NO_ERROR), \"could not compute mintable amount\");\n\n // check that user have sufficient mintableVAI balance\n require(mintVAIAmount <= accountMintableVAI, \"minting more than allowed\");\n\n // Calculate the minted balance based on interest index\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\n\n if (totalMintedVAI > 0) {\n uint256 repayAmount = getVAIRepayAmount(minter);\n uint256 remainedAmount = sub_(repayAmount, totalMintedVAI);\n pastVAIInterest[minter] = add_(pastVAIInterest[minter], remainedAmount);\n totalMintedVAI = repayAmount;\n }\n\n uint256 accountMintVAINew = add_(totalMintedVAI, mintVAIAmount);\n err = comptroller.setMintedVAIOf(minter, accountMintVAINew);\n require(err == uint256(Error.NO_ERROR), \"comptroller rejection\");\n\n uint256 remainedAmount;\n if (treasuryPercent != 0) {\n uint256 feeAmount = div_(mul_(mintVAIAmount, treasuryPercent), 1e18);\n remainedAmount = sub_(mintVAIAmount, feeAmount);\n IVAI(_vai).mint(treasuryAddress, feeAmount);\n\n emit MintFee(minter, feeAmount);\n } else {\n remainedAmount = mintVAIAmount;\n }\n\n IVAI(_vai).mint(minter, remainedAmount);\n vaiMinterInterestIndex[minter] = vaiMintIndex;\n\n emit MintVAI(minter, remainedAmount);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice The repay function transfers VAI interest into the protocol and burns the rest,\n * reducing the borrower's borrow balance. Before repaying VAI, users must first approve\n * VAIController to access their VAI balance.\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\n * @param amount The amount of VAI to be repaid.\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function repayVAI(uint256 amount) external nonReentrant returns (uint256, uint256) {\n return _repayVAI(msg.sender, amount);\n }\n\n /**\n * @notice The repay on behalf function transfers VAI interest into the protocol and burns the rest,\n * reducing the borrower's borrow balance. Borrowed VAIs are repaid by another user (possibly the borrower).\n * Before repaying VAI, the payer must first approve VAIController to access their VAI balance.\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\n * @param borrower The account to repay the debt for.\n * @param amount The amount of VAI to be repaid.\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function repayVAIBehalf(address borrower, uint256 amount) external nonReentrant returns (uint256, uint256) {\n _ensureNonzeroAddress(borrower);\n return _repayVAI(borrower, amount);\n }\n\n /**\n * @dev Checks the parameters and the protocol state, accrues interest, and invokes repayVAIFresh.\n * @dev If the Comptroller address is not set, repayment is a no-op and the function returns the success code.\n * @param borrower The account to repay the debt for.\n * @param amount The amount of VAI to be repaid.\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function _repayVAI(address borrower, uint256 amount) internal returns (uint256, uint256) {\n if (address(comptroller) == address(0)) {\n return (0, 0);\n }\n _ensureNonzeroAmount(amount);\n _ensureNotPaused();\n\n accrueVAIInterest();\n return repayVAIFresh(msg.sender, borrower, amount);\n }\n\n /**\n * @dev Repay VAI, expecting interest to be accrued\n * @dev Borrowed VAIs are repaid by another user (possibly the borrower).\n * @param payer the account paying off the VAI\n * @param borrower the account with the debt being payed off\n * @param repayAmount the amount of VAI being repaid\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function repayVAIFresh(address payer, address borrower, uint256 repayAmount) internal returns (uint256, uint256) {\n (uint256 burn, uint256 partOfCurrentInterest, uint256 partOfPastInterest) = getVAICalculateRepayAmount(\n borrower,\n repayAmount\n );\n\n IVAI _vai = IVAI(vai);\n _vai.burn(payer, burn);\n bool success = _vai.transferFrom(payer, receiver, partOfCurrentInterest);\n require(success == true, \"failed to transfer VAI fee\");\n\n uint256 vaiBalanceBorrower = comptroller.mintedVAIs(borrower);\n\n uint256 accountVAINew = sub_(sub_(vaiBalanceBorrower, burn), partOfPastInterest);\n pastVAIInterest[borrower] = sub_(pastVAIInterest[borrower], partOfPastInterest);\n\n uint256 error = comptroller.setMintedVAIOf(borrower, accountVAINew);\n // We have to revert upon error since side-effects already happened at this point\n require(error == uint256(Error.NO_ERROR), \"comptroller rejection\");\n\n uint256 repaidAmount = add_(burn, partOfCurrentInterest);\n emit RepayVAI(payer, borrower, repaidAmount);\n\n return (uint256(Error.NO_ERROR), repaidAmount);\n }\n\n /**\n * @notice The sender liquidates the vai minters collateral. The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of vai to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function liquidateVAI(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external nonReentrant returns (uint256, uint256) {\n _ensureNotPaused();\n\n uint256 error = vTokenCollateral.accrueInterest();\n if (error != uint256(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\n }\n\n // liquidateVAIFresh emits borrow-specific logs on errors, so we don't need to\n return liquidateVAIFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral by repay borrowers VAI.\n * The collateral seized is transferred to the liquidator.\n * @dev If the Comptroller address is not set, liquidation is a no-op and the function returns the success code.\n * @param liquidator The address repaying the VAI and seizing collateral\n * @param borrower The borrower of this VAI to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the VAI to repay\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol)\n * @return Actual repayment amount\n */\n function liquidateVAIFresh(\n address liquidator,\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) internal returns (uint256, uint256) {\n if (address(comptroller) != address(0)) {\n accrueVAIInterest();\n\n /* Fail if liquidate not allowed */\n uint256 allowed = comptroller.liquidateBorrowAllowed(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n repayAmount\n );\n if (allowed != 0) {\n return (failOpaque(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n //if (vTokenCollateral.accrualBlockNumber() != accrualBlockNumber) {\n if (vTokenCollateral.accrualBlockNumber() != getBlockNumber()) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n return (fail(Error.REJECTION, FailureInfo.VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n /* Fail if repayVAI fails */\n (uint256 repayBorrowError, uint256 actualRepayAmount) = repayVAIFresh(liquidator, borrower, repayAmount);\n if (repayBorrowError != uint256(Error.NO_ERROR)) {\n return (fail(Error(repayBorrowError), FailureInfo.VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint256 amountSeizeError, uint256 seizeTokens) = comptroller.liquidateVAICalculateSeizeTokens(\n address(vTokenCollateral),\n actualRepayAmount\n );\n require(\n amountSeizeError == uint256(Error.NO_ERROR),\n \"VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\"\n );\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"VAI_LIQUIDATE_SEIZE_TOO_MUCH\");\n\n uint256 seizeError;\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\n require(seizeError == uint256(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateVAI(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n\n /* We call the defense hook */\n comptroller.liquidateBorrowVerify(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n actualRepayAmount,\n seizeTokens\n );\n\n return (uint256(Error.NO_ERROR), actualRepayAmount);\n }\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Sets a new comptroller\n * @dev Admin function to set a new comptroller\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setComptroller(ComptrollerInterface comptroller_) external returns (uint256) {\n // Check caller is admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_COMPTROLLER_OWNER_CHECK);\n }\n\n ComptrollerInterface oldComptroller = comptroller;\n comptroller = comptroller_;\n emit NewComptroller(oldComptroller, comptroller_);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Set the prime token contract address\n * @param prime_ The new address of the prime token contract\n */\n function setPrimeToken(address prime_) external onlyAdmin {\n emit NewPrime(prime, prime_);\n prime = prime_;\n }\n\n /**\n * @notice Set the VAI token contract address\n * @param vai_ The new address of the VAI token contract\n */\n function setVAIToken(address vai_) external onlyAdmin {\n emit NewVaiToken(vai, vai_);\n vai = vai_;\n }\n\n /**\n * @notice Toggle mint only for prime holder\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function toggleOnlyPrimeHolderMint() external returns (uint256) {\n _ensureAllowed(\"toggleOnlyPrimeHolderMint()\");\n\n if (!mintEnabledOnlyForPrimeHolder && prime == address(0)) {\n return uint256(Error.REJECTION);\n }\n\n emit MintOnlyForPrimeHolder(mintEnabledOnlyForPrimeHolder, !mintEnabledOnlyForPrimeHolder);\n mintEnabledOnlyForPrimeHolder = !mintEnabledOnlyForPrimeHolder;\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Local vars for avoiding stack-depth limits in calculating account total supply balance.\n * Note that `vTokenBalance` is the number of vTokens the account owns in the market,\n * whereas `borrowBalance` is the amount of underlying that the account has borrowed.\n */\n struct AccountAmountLocalVars {\n uint256 oErr;\n MathError mErr;\n uint256 sumSupply;\n uint256 marketSupply;\n uint256 sumBorrowPlusEffects;\n uint256 vTokenBalance;\n uint256 borrowBalance;\n uint256 exchangeRateMantissa;\n uint256 collateralPriceMantissa;\n uint256 debtPriceMantissa;\n Exp exchangeRate;\n Exp collateralPrice;\n Exp debtPrice;\n Exp tokensToDenom;\n }\n\n /**\n * @notice Function that returns the amount of VAI a user can mint based on their account liquidy and the VAI mint rate\n * If mintEnabledOnlyForPrimeHolder is true, only Prime holders are able to mint VAI\n * @param minter The account to check mintable VAI\n * @return Error code (0=success, otherwise a failure, see ErrorReporter.sol for details)\n * @return Mintable amount (with 18 decimals)\n */\n // solhint-disable-next-line code-complexity\n function getMintableVAI(address minter) public view returns (uint256, uint256) {\n if (mintEnabledOnlyForPrimeHolder && !IPrime(prime).isUserPrimeHolder(minter)) {\n return (uint256(Error.REJECTION), 0);\n }\n\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\n IDeviationBoundedOracle boundedOracle = comptroller.deviationBoundedOracle();\n\n AccountAmountLocalVars memory vars; // Holds all our calculation results\n\n uint256 accountMintableVAI;\n uint256 i;\n\n /**\n * We use this formula to calculate mintable VAI amount.\n * totalSupplyAmount * VAIMintRate - (totalBorrowAmount + mintedVAIOf)\n */\n uint256 marketsCount = enteredMarkets.length;\n for (i = 0; i < marketsCount; i++) {\n (vars.oErr, vars.vTokenBalance, vars.borrowBalance, vars.exchangeRateMantissa) = enteredMarkets[i]\n .getAccountSnapshot(minter);\n if (vars.oErr != 0) {\n // semi-opaque error code, we assume NO_ERROR == 0 is invariant between upgrades\n return (uint256(Error.SNAPSHOT_ERROR), 0);\n }\n vars.exchangeRate = Exp({ mantissa: vars.exchangeRateMantissa });\n\n // Get bounded prices: collateral price for supply valuation, debt price for borrow valuation\n (vars.collateralPriceMantissa, vars.debtPriceMantissa) = boundedOracle.getBoundedPricesView(\n address(enteredMarkets[i])\n );\n if (vars.collateralPriceMantissa == 0 || vars.debtPriceMantissa == 0) {\n return (uint256(Error.PRICE_ERROR), 0);\n }\n vars.collateralPrice = Exp({ mantissa: vars.collateralPriceMantissa });\n vars.debtPrice = Exp({ mantissa: vars.debtPriceMantissa });\n\n (vars.mErr, vars.tokensToDenom) = mulExp(vars.exchangeRate, vars.collateralPrice);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n // marketSupply = tokensToDenom * vTokenBalance\n (vars.mErr, vars.marketSupply) = mulScalarTruncate(vars.tokensToDenom, vars.vTokenBalance);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n (, uint256 collateralFactorMantissa, , , , , ) = comptroller.markets(address(enteredMarkets[i]));\n (vars.mErr, vars.marketSupply) = mulUInt(vars.marketSupply, collateralFactorMantissa);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, vars.marketSupply) = divUInt(vars.marketSupply, 1e18);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, vars.sumSupply) = addUInt(vars.sumSupply, vars.marketSupply);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n // sumBorrowPlusEffects += debtPrice * borrowBalance\n (vars.mErr, vars.sumBorrowPlusEffects) = mulScalarTruncateAddUInt(\n vars.debtPrice,\n vars.borrowBalance,\n vars.sumBorrowPlusEffects\n );\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n }\n\n uint256 totalMintedVAI = comptroller.mintedVAIs(minter);\n uint256 repayAmount = 0;\n\n if (totalMintedVAI > 0) {\n repayAmount = getVAIRepayAmount(minter);\n }\n\n (vars.mErr, vars.sumBorrowPlusEffects) = addUInt(vars.sumBorrowPlusEffects, repayAmount);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.MATH_ERROR), 0);\n }\n\n (vars.mErr, accountMintableVAI) = mulUInt(vars.sumSupply, comptroller.vaiMintRate());\n require(vars.mErr == MathError.NO_ERROR, \"VAI_MINT_AMOUNT_CALCULATION_FAILED\");\n\n (vars.mErr, accountMintableVAI) = divUInt(accountMintableVAI, 10000);\n require(vars.mErr == MathError.NO_ERROR, \"VAI_MINT_AMOUNT_CALCULATION_FAILED\");\n\n (vars.mErr, accountMintableVAI) = subUInt(accountMintableVAI, vars.sumBorrowPlusEffects);\n if (vars.mErr != MathError.NO_ERROR) {\n return (uint256(Error.REJECTION), 0);\n }\n\n return (uint256(Error.NO_ERROR), accountMintableVAI);\n }\n\n /**\n * @notice Update treasury data\n * @param newTreasuryGuardian New Treasury Guardian address\n * @param newTreasuryAddress New Treasury Address\n * @param newTreasuryPercent New fee percentage for minting VAI that is sent to the treasury\n */\n function _setTreasuryData(\n address newTreasuryGuardian,\n address newTreasuryAddress,\n uint256 newTreasuryPercent\n ) external returns (uint256) {\n // Check caller is admin\n if (!(msg.sender == admin || msg.sender == treasuryGuardian)) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_TREASURY_OWNER_CHECK);\n }\n\n require(newTreasuryPercent < 1e18, \"treasury percent cap overflow\");\n\n address oldTreasuryGuardian = treasuryGuardian;\n address oldTreasuryAddress = treasuryAddress;\n uint256 oldTreasuryPercent = treasuryPercent;\n\n treasuryGuardian = newTreasuryGuardian;\n treasuryAddress = newTreasuryAddress;\n treasuryPercent = newTreasuryPercent;\n\n emit NewTreasuryGuardian(oldTreasuryGuardian, newTreasuryGuardian);\n emit NewTreasuryAddress(oldTreasuryAddress, newTreasuryAddress);\n emit NewTreasuryPercent(oldTreasuryPercent, newTreasuryPercent);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Gets yearly VAI interest rate based on the VAI price\n * @return uint256 Yearly VAI interest rate\n */\n function getVAIRepayRate() public view returns (uint256) {\n ResilientOracleInterface oracle = comptroller.oracle();\n MathError mErr;\n\n if (baseRateMantissa > 0) {\n if (floatRateMantissa > 0) {\n uint256 oraclePrice = oracle.getUnderlyingPrice(getVAIAddress());\n if (1e18 > oraclePrice) {\n uint256 delta;\n uint256 rate;\n\n (mErr, delta) = subUInt(1e18, oraclePrice);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, delta) = mulUInt(delta, floatRateMantissa);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, delta) = divUInt(delta, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n (mErr, rate) = addUInt(delta, baseRateMantissa);\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n return rate;\n } else {\n return baseRateMantissa;\n }\n } else {\n return baseRateMantissa;\n }\n } else {\n return 0;\n }\n }\n\n /**\n * @notice Get interest rate per block\n * @return uint256 Interest rate per bock\n */\n function getVAIRepayRatePerBlock() public view returns (uint256) {\n uint256 yearlyRate = getVAIRepayRate();\n\n MathError mErr;\n uint256 rate;\n\n (mErr, rate) = divUInt(yearlyRate, getBlocksPerYear());\n require(mErr == MathError.NO_ERROR, \"VAI_REPAY_RATE_CALCULATION_FAILED\");\n\n return rate;\n }\n\n /**\n * @notice Get the last updated interest index for a VAI Minter\n * @param minter Address of VAI minter\n * @return uint256 Returns the interest rate index for a minter\n */\n function getVAIMinterInterestIndex(address minter) public view returns (uint256) {\n uint256 storedIndex = vaiMinterInterestIndex[minter];\n // If the user minted VAI before the stability fee was introduced, accrue\n // starting from stability fee launch\n if (storedIndex == 0) {\n return INITIAL_VAI_MINT_INDEX;\n }\n return storedIndex;\n }\n\n /**\n * @notice Get the current total VAI a user needs to repay\n * @param account The address of the VAI borrower\n * @return (uint256) The total amount of VAI the user needs to repay\n */\n function getVAIRepayAmount(address account) public view returns (uint256) {\n MathError mErr;\n uint256 delta;\n\n uint256 amount = comptroller.mintedVAIs(account);\n uint256 interest = pastVAIInterest[account];\n uint256 totalMintedVAI;\n uint256 newInterest;\n\n (mErr, totalMintedVAI) = subUInt(amount, interest);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, delta) = subUInt(vaiMintIndex, getVAIMinterInterestIndex(account));\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, newInterest) = mulUInt(delta, totalMintedVAI);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, newInterest) = divUInt(newInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, amount) = addUInt(amount, newInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_TOTAL_REPAY_AMOUNT_CALCULATION_FAILED\");\n\n return amount;\n }\n\n /**\n * @notice Calculate how much VAI the user needs to repay\n * @param borrower The address of the VAI borrower\n * @param repayAmount The amount of VAI being returned\n * @return Amount of VAI to be burned\n * @return Amount of VAI the user needs to pay in current interest\n * @return Amount of VAI the user needs to pay in past interest\n */\n function getVAICalculateRepayAmount(\n address borrower,\n uint256 repayAmount\n ) public view returns (uint256, uint256, uint256) {\n MathError mErr;\n uint256 totalRepayAmount = getVAIRepayAmount(borrower);\n uint256 currentInterest;\n\n (mErr, currentInterest) = subUInt(totalRepayAmount, comptroller.mintedVAIs(borrower));\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, currentInterest) = addUInt(pastVAIInterest[borrower], currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n uint256 burn;\n uint256 partOfCurrentInterest = currentInterest;\n uint256 partOfPastInterest = pastVAIInterest[borrower];\n\n if (repayAmount >= totalRepayAmount) {\n (mErr, burn) = subUInt(totalRepayAmount, currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n } else {\n uint256 delta;\n\n (mErr, delta) = mulUInt(repayAmount, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_PART_CALCULATION_FAILED\");\n\n (mErr, delta) = divUInt(delta, totalRepayAmount);\n require(mErr == MathError.NO_ERROR, \"VAI_PART_CALCULATION_FAILED\");\n\n uint256 totalMintedAmount;\n (mErr, totalMintedAmount) = subUInt(totalRepayAmount, currentInterest);\n require(mErr == MathError.NO_ERROR, \"VAI_MINTED_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, burn) = mulUInt(totalMintedAmount, delta);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, burn) = divUInt(burn, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_BURN_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfCurrentInterest) = mulUInt(currentInterest, delta);\n require(mErr == MathError.NO_ERROR, \"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfCurrentInterest) = divUInt(partOfCurrentInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_CURRENT_INTEREST_AMOUNT_CALCULATION_FAILED\");\n\n (mErr, partOfPastInterest) = mulUInt(pastVAIInterest[borrower], delta);\n require(mErr == MathError.NO_ERROR, \"VAI_PAST_INTEREST_CALCULATION_FAILED\");\n\n (mErr, partOfPastInterest) = divUInt(partOfPastInterest, 1e18);\n require(mErr == MathError.NO_ERROR, \"VAI_PAST_INTEREST_CALCULATION_FAILED\");\n }\n\n return (burn, partOfCurrentInterest, partOfPastInterest);\n }\n\n /**\n * @notice Accrue interest on outstanding minted VAI\n */\n function accrueVAIInterest() public {\n MathError mErr;\n uint256 delta;\n\n (mErr, delta) = mulUInt(getVAIRepayRatePerBlock(), getBlockNumber() - accrualBlockNumber);\n require(mErr == MathError.NO_ERROR, \"VAI_INTEREST_ACCRUE_FAILED\");\n\n (mErr, delta) = addUInt(delta, vaiMintIndex);\n require(mErr == MathError.NO_ERROR, \"VAI_INTEREST_ACCRUE_FAILED\");\n\n vaiMintIndex = delta;\n accrualBlockNumber = getBlockNumber();\n }\n\n /**\n * @notice Sets the address of the access control of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlAddress New address for the access control\n */\n function setAccessControl(address newAccessControlAddress) external onlyAdmin {\n _ensureNonzeroAddress(newAccessControlAddress);\n\n address oldAccessControlAddress = accessControl;\n accessControl = newAccessControlAddress;\n emit NewAccessControl(oldAccessControlAddress, accessControl);\n }\n\n /**\n * @notice Set VAI borrow base rate\n * @param newBaseRateMantissa the base rate multiplied by 10**18\n */\n function setBaseRate(uint256 newBaseRateMantissa) external {\n _ensureAllowed(\"setBaseRate(uint256)\");\n\n uint256 old = baseRateMantissa;\n baseRateMantissa = newBaseRateMantissa;\n emit NewVAIBaseRate(old, baseRateMantissa);\n }\n\n /**\n * @notice Set VAI borrow float rate\n * @param newFloatRateMantissa the VAI float rate multiplied by 10**18\n */\n function setFloatRate(uint256 newFloatRateMantissa) external {\n _ensureAllowed(\"setFloatRate(uint256)\");\n\n uint256 old = floatRateMantissa;\n floatRateMantissa = newFloatRateMantissa;\n emit NewVAIFloatRate(old, floatRateMantissa);\n }\n\n /**\n * @notice Set VAI stability fee receiver address\n * @param newReceiver the address of the VAI fee receiver\n */\n function setReceiver(address newReceiver) external onlyAdmin {\n _ensureNonzeroAddress(newReceiver);\n\n address old = receiver;\n receiver = newReceiver;\n emit NewVAIReceiver(old, newReceiver);\n }\n\n /**\n * @notice Set VAI mint cap\n * @param _mintCap the amount of VAI that can be minted\n */\n function setMintCap(uint256 _mintCap) external {\n _ensureAllowed(\"setMintCap(uint256)\");\n\n uint256 old = mintCap;\n mintCap = _mintCap;\n emit NewVAIMintCap(old, _mintCap);\n }\n\n function getBlockNumber() internal view virtual returns (uint256) {\n return block.number;\n }\n\n function getBlocksPerYear() public view virtual returns (uint256) {\n return 70080000; //(24 * 60 * 60 * 365) / 0.45;\n }\n\n /**\n * @notice Return the address of the VAI token\n * @return The address of VAI\n */\n function getVAIAddress() public view virtual returns (address) {\n return vai;\n }\n\n modifier onlyAdmin() {\n require(msg.sender == admin, \"only admin can\");\n _;\n }\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n function _ensureAllowed(string memory functionSig) private view {\n require(IAccessControlManagerV8(accessControl).isAllowedToCall(msg.sender, functionSig), \"access denied\");\n }\n\n /// @dev Reverts if the protocol is paused\n function _ensureNotPaused() private view {\n require(!comptroller.protocolPaused(), \"protocol is paused\");\n }\n\n /// @dev Reverts if the passed address is zero\n function _ensureNonzeroAddress(address someone) private pure {\n require(someone != address(0), \"can't be zero address\");\n }\n\n /// @dev Reverts if the passed amount is zero\n function _ensureNonzeroAmount(uint256 amount) private pure {\n require(amount > 0, \"amount can't be zero\");\n }\n\n /// @dev Persists the DBO protection window for every market the minter has entered, so VAI minting\n /// records the same on-chain price history as the borrow path. Extracted from `mintVAI` to avoid\n /// stack-too-deep in that function.\n function _updateProtectionStateForEnteredMarkets(address minter) private {\n IDeviationBoundedOracle dbo = comptroller.deviationBoundedOracle();\n VToken[] memory enteredMarkets = comptroller.getAssetsIn(minter);\n uint256 enteredLength = enteredMarkets.length;\n for (uint256 i; i < enteredLength; ++i) {\n dbo.updateProtectionState(address(enteredMarkets[i]));\n }\n }\n}\n" + }, + "contracts/Tokens/VAI/VAIControllerInterface.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VTokenInterface } from \"../VTokens/VTokenInterfaces.sol\";\n\ninterface VAIControllerInterface {\n function mintVAI(uint256 mintVAIAmount) external returns (uint256);\n\n function repayVAI(uint256 amount) external returns (uint256, uint256);\n\n function repayVAIBehalf(address borrower, uint256 amount) external returns (uint256, uint256);\n\n function liquidateVAI(\n address borrower,\n uint256 repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint256, uint256);\n\n function getMintableVAI(address minter) external view returns (uint256, uint256);\n\n function getVAIAddress() external view returns (address);\n\n function getVAIRepayAmount(address account) external view returns (uint256);\n}\n" + }, + "contracts/Tokens/VAI/VAIControllerStorage.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\n\ncontract VAIUnitrollerAdminStorage {\n /**\n * @notice Administrator for this contract\n */\n address public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address public pendingAdmin;\n\n /**\n * @notice Active brains of Unitroller\n */\n address public vaiControllerImplementation;\n\n /**\n * @notice Pending brains of Unitroller\n */\n address public pendingVAIControllerImplementation;\n}\n\ncontract VAIControllerStorageG1 is VAIUnitrollerAdminStorage {\n ComptrollerInterface public comptroller;\n\n struct VenusVAIState {\n /// @notice The last updated venusVAIMintIndex\n uint224 index;\n /// @notice The block number the index was last updated at\n uint32 block;\n }\n\n /// @notice The Venus VAI state\n VenusVAIState public venusVAIState;\n\n /// @notice The Venus VAI state initialized\n bool public isVenusVAIInitialized;\n\n /// @notice The Venus VAI minter index as of the last time they accrued XVS\n mapping(address => uint256) public venusVAIMinterIndex;\n}\n\ncontract VAIControllerStorageG2 is VAIControllerStorageG1 {\n /// @notice Treasury Guardian address\n address public treasuryGuardian;\n\n /// @notice Treasury address\n address public treasuryAddress;\n\n /// @notice Fee percent of accrued interest with decimal 18\n uint256 public treasuryPercent;\n\n /// @notice Guard variable for re-entrancy checks\n bool internal _notEntered;\n\n /// @notice The base rate for stability fee\n uint256 public baseRateMantissa;\n\n /// @notice The float rate for stability fee\n uint256 public floatRateMantissa;\n\n /// @notice The address for VAI interest receiver\n address public receiver;\n\n /// @notice Accumulator of the total earned interest rate since the opening of the market. For example: 0.6 (60%)\n uint256 public vaiMintIndex;\n\n /// @notice Block number that interest was last accrued at\n uint256 internal accrualBlockNumber;\n\n /// @notice Global vaiMintIndex as of the most recent balance-changing action for user\n mapping(address => uint256) internal vaiMinterInterestIndex;\n\n /// @notice Tracks the amount of mintedVAI of a user that represents the accrued interest\n mapping(address => uint256) public pastVAIInterest;\n\n /// @notice VAI mint cap\n uint256 public mintCap;\n\n /// @notice Access control manager address\n address public accessControl;\n}\n\ncontract VAIControllerStorageG3 is VAIControllerStorageG2 {\n /// @notice The address of the prime contract. It can be a ZERO address\n address public prime;\n\n /// @notice Tracks if minting is enabled only for prime token holders. Only used if prime is set\n bool public mintEnabledOnlyForPrimeHolder;\n}\n\ncontract VAIControllerStorageG4 is VAIControllerStorageG3 {\n /// @notice The address of the VAI token\n address internal vai;\n}\n" + }, + "contracts/Tokens/VAI/VAIUnitroller.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { VAIControllerErrorReporter } from \"../../Utils/ErrorReporter.sol\";\nimport { VAIUnitrollerAdminStorage } from \"./VAIControllerStorage.sol\";\n\n/**\n * @title VAI Unitroller\n * @author Venus\n * @notice This is the proxy contract for the VAIComptroller\n */\ncontract VAIUnitroller is VAIUnitrollerAdminStorage, VAIControllerErrorReporter {\n /**\n * @notice Emitted when pendingVAIControllerImplementation is changed\n */\n event NewPendingImplementation(address oldPendingImplementation, address newPendingImplementation);\n\n /**\n * @notice Emitted when pendingVAIControllerImplementation is accepted, which means comptroller implementation is updated\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Emitted when pendingAdmin is accepted, which means admin is updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n constructor() {\n // Set admin to caller\n admin = msg.sender;\n }\n\n /*** Admin Functions ***/\n function _setPendingImplementation(address newPendingImplementation) public returns (uint256) {\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_IMPLEMENTATION_OWNER_CHECK);\n }\n\n address oldPendingImplementation = pendingVAIControllerImplementation;\n\n pendingVAIControllerImplementation = newPendingImplementation;\n\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts new implementation of comptroller. msg.sender must be pendingImplementation\n * @dev Admin function for new implementation to accept it's role as implementation\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptImplementation() public returns (uint256) {\n // Check caller is pendingImplementation\n if (msg.sender != pendingVAIControllerImplementation) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldImplementation = vaiControllerImplementation;\n address oldPendingImplementation = pendingVAIControllerImplementation;\n\n vaiControllerImplementation = pendingVAIControllerImplementation;\n\n pendingVAIControllerImplementation = address(0);\n\n emit NewImplementation(oldImplementation, vaiControllerImplementation);\n emit NewPendingImplementation(oldPendingImplementation, pendingVAIControllerImplementation);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _setPendingAdmin(address newPendingAdmin) public returns (uint256) {\n // Check caller = admin\n if (msg.sender != admin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.SET_PENDING_ADMIN_OWNER_CHECK);\n }\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint256 0=success, otherwise a failure (see ErrorReporter.sol for details)\n */\n function _acceptAdmin() public returns (uint256) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = address(0);\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint256(Error.NO_ERROR);\n }\n\n /**\n * @dev Delegates execution to an implementation contract.\n * It returns to the external caller whatever the implementation returns\n * or forwards reverts.\n */\n fallback() external {\n // delegate all other functions to current implementation\n (bool success, ) = vaiControllerImplementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VBep20Interface, VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { VToken } from \"./VToken.sol\";\n\n/**\n * @title Venus's VBep20 Contract\n * @notice vTokens which wrap an ERC-20 underlying\n * @author Venus\n */\ncontract VBep20 is VToken, VBep20Interface {\n using SafeERC20 for IERC20;\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits Mint event\n function mint(uint mintAmount) external returns (uint) {\n (uint err, ) = mintInternal(mintAmount);\n return err;\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver The account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits MintBehalf event\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n (uint err, ) = mintBehalfInternal(receiver, mintAmount);\n return err;\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemer The user on behalf of whom to redeem\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemBehalf(address redeemer, uint redeemTokens) external returns (uint) {\n require(comptroller.approvedDelegates(redeemer, msg.sender), \"not an approved delegate\");\n\n return redeemInternal(redeemer, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemer, on behalf of whom to redeem\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlyingBehalf(address redeemer, uint redeemAmount) external returns (uint) {\n require(comptroller.approvedDelegates(redeemer, msg.sender), \"not an approved delegate\");\n\n return redeemUnderlyingInternal(redeemer, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender borrows assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the borrower using `comptroller.updateDelegate`\n * @param borrower The borrower, on behalf of whom to borrow.\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrowBehalf(address borrower, uint borrowAmount) external returns (uint) {\n require(comptroller.approvedDelegates(borrower, msg.sender), \"not an approved delegate\");\n return borrowInternal(borrower, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrow(uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowInternal(repayAmount);\n return err;\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrowing account\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n (uint err, ) = repayBorrowBehalfInternal(borrower, repayAmount);\n return err;\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emit LiquidateBorrow event on success\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n (uint err, ) = liquidateBorrowInternal(borrower, repayAmount, vTokenCollateral);\n return err;\n }\n\n /**\n * @notice The sender adds to reserves.\n * @param addAmount The amount of underlying tokens to add as reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesAdded event\n function _addReserves(uint addAmount) external returns (uint) {\n return _addReservesInternal(addAmount);\n }\n\n /**\n * @notice Initialize the new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n */\n function initialize(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n // VToken initialize does the bulk of the work\n super.initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set underlying and sanity check it\n underlying = underlying_;\n IERC20(underlying).totalSupply();\n }\n\n /*** Safe Token ***/\n\n /**\n * @dev Similar to ERC-20 transfer, but handles tokens that have transfer fees.\n * This function returns the actual amount received,\n * which may be less than `amount` if there is a fee attached to the transfer.\n * Increments `internalCash` by the actual amount received.\n * @param from Sender of the underlying tokens\n * @param amount Amount of underlying to transfer\n * @return Actual amount received\n */\n function doTransferIn(address from, uint256 amount) internal virtual override returns (uint256) {\n IERC20 token = IERC20(underlying);\n uint256 balanceBefore = token.balanceOf(address(this));\n token.safeTransferFrom(from, address(this), amount);\n uint256 balanceAfter = token.balanceOf(address(this));\n uint256 actualAmount = balanceAfter - balanceBefore;\n internalCash += actualAmount;\n // Return the amount that was *actually* transferred\n return actualAmount;\n }\n\n /**\n * @dev Just a regular ERC-20 transfer, reverts on failure.\n * Decrements `internalCash` by `amount` before transferring.\n * @param to Receiver of the underlying tokens\n * @param amount Amount of underlying to transfer\n */\n function doTransferOut(address payable to, uint256 amount) internal virtual override {\n internalCash -= amount;\n IERC20 token = IERC20(underlying);\n token.safeTransfer(to, amount);\n }\n\n /**\n * @notice Gets the tracked internal cash balance of this contract\n * @dev Returns `internalCash` rather than the actual token balance, making it immune to donation attacks.\n * @return The internally tracked cash balance of underlying tokens\n */\n function getCashPrior() internal view override returns (uint) {\n return internalCash;\n }\n\n /**\n * @notice Transfer excess tokens to caller and sync internalCash with actual balance\n * @dev Admin-only. For migration: pass 0 (just syncs). For sweep: pass the excess amount.\n * Transfers `transferAmount` of underlying to msg.sender, then sets internalCash = balanceOf(address(this)).\n * @param transferAmount Amount of underlying to transfer to msg.sender before syncing\n */\n function sweepTokenAndSync(uint256 transferAmount) external {\n require(msg.sender == admin);\n\n if (transferAmount > 0) {\n IERC20(underlying).safeTransfer(msg.sender, transferAmount);\n emit TokenSwept(msg.sender, transferAmount);\n }\n\n uint256 oldInternalCash = internalCash;\n internalCash = IERC20(underlying).balanceOf(address(this));\n emit CashSynced(oldInternalCash, internalCash);\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Delegate.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { VBep20 } from \"./VBep20.sol\";\nimport { VDelegateInterface } from \"./VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20Delegate Contract\n * @notice VTokens which wrap an EIP-20 underlying and are delegated to\n * @author Venus\n */\ncontract VBep20Delegate is VBep20, VDelegateInterface {\n /**\n * @notice Construct an empty delegate\n */\n constructor() {}\n\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) public {\n // Shh -- currently unused\n data;\n\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _becomeImplementation\");\n }\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() public {\n // Shh -- we don't ever want this hook to be marked pure\n if (false) {\n implementation = address(0);\n }\n\n require(msg.sender == admin, \"only the admin may call _resignImplementation\");\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Delegator.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VTokenInterface, VBep20Interface, VDelegatorInterface } from \"./VTokenInterfaces.sol\";\n\n/**\n * @title Venus's VBep20Delegator Contract\n * @notice vTokens which wrap an EIP-20 underlying and delegate to an implementation\n * @author Venus\n */\ncontract VBep20Delegator is VTokenInterface, VBep20Interface, VDelegatorInterface {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n * @param implementation_ The address of the implementation the contract delegates to\n * @param becomeImplementationData The encoded args for becomeImplementation\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_,\n address implementation_,\n bytes memory becomeImplementationData\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n // First delegate gets to initialize the delegator (i.e. storage contract)\n delegateTo(\n implementation_,\n abi.encodeWithSignature(\n \"initialize(address,address,address,uint256,string,string,uint8)\",\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n )\n );\n\n // New implementations always get set via the settor (post-initialize)\n _setImplementation(implementation_, false, becomeImplementationData);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n */\n fallback() external {\n // delegate all other functions to current implementation\n (bool success, ) = implementation.delegatecall(msg.data);\n\n assembly {\n let free_mem_ptr := mload(0x40)\n returndatacopy(free_mem_ptr, 0, returndatasize())\n\n switch success\n case 0 {\n revert(free_mem_ptr, returndatasize())\n }\n default {\n return(free_mem_ptr, returndatasize())\n }\n }\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function mint(uint mintAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"mint(uint256)\", mintAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function mintBehalf(address receiver, uint mintAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"mintBehalf(address,uint256)\", receiver, mintAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying asset\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeem(uint redeemTokens) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"redeem(uint256)\", redeemTokens));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"redeemUnderlying(uint256)\", redeemAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function borrow(uint borrowAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrow(uint256)\", borrowAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function repayBorrow(uint repayAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"repayBorrow(uint256)\", repayAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrower\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"repayBorrowBehalf(address,uint256)\", borrower, repayAmount)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"liquidateBorrow(address,uint256,address)\", borrower, repayAmount, vTokenCollateral)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"transfer(address,uint256)\", dst, amount));\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"transferFrom(address,address,uint256)\", src, dst, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint256 amount) external override returns (bool) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"approve(address,uint256)\", spender, amount)\n );\n return abi.decode(data, (bool));\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"balanceOfUnderlying(address)\", owner));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"totalBorrowsCurrent()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"borrowBalanceCurrent(address)\", account));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * It's absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function seize(address liquidator, address borrower, uint seizeTokens) external override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"seize(address,address,uint256)\", liquidator, borrower, seizeTokens)\n );\n return abi.decode(data, (uint));\n }\n\n /*** Admin Functions ***/\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setPendingAdmin(address)\", newPendingAdmin)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and sets a new reserve factor for the protocol using _setReserveFactorFresh\n * @dev Admin function to accrue interest and set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setReserveFactor(uint newReserveFactorMantissa) external override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setReserveFactor(uint256)\", newReserveFactorMantissa)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accepts transfer of admin rights. `msg.sender` must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _acceptAdmin() external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_acceptAdmin()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from admin\n * @param addAmount Amount of reserves to add\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _addReserves(uint addAmount) external returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_addReserves(uint256)\", addAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to admin\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReserves(uint reduceAmount) external override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"_reduceReserves(uint256)\", reduceAmount));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"getCash()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"allowance(address,address)\", owner, spender)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"balanceOf(address)\", owner));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Get a snapshot of the account's balances and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"getAccountSnapshot(address)\", account)\n );\n return abi.decode(data, (uint, uint, uint, uint));\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"borrowRatePerBlock()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"supplyRatePerBlock()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n // @custom:access Only callable by admin\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) public {\n require(msg.sender == admin, \"VBep20Delegator::_setImplementation: Caller must be admin\");\n\n if (allowResign) {\n delegateToImplementation(abi.encodeWithSignature(\"_resignImplementation()\"));\n }\n\n address oldImplementation = implementation;\n implementation = implementation_;\n\n delegateToImplementation(abi.encodeWithSignature(\"_becomeImplementation(bytes)\", becomeImplementationData));\n\n emit NewImplementation(oldImplementation, implementation);\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"exchangeRateCurrent()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves.\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage.\n */\n function accrueInterest() public override returns (uint) {\n bytes memory data = delegateToImplementation(abi.encodeWithSignature(\"accrueInterest()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setComptroller(address)\", newComptroller)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using `_setInterestRateModelFresh`\n * @dev Admin function to accrue interest and update the interest rate model\n * @param newInterestRateModel The new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public override returns (uint) {\n bytes memory data = delegateToImplementation(\n abi.encodeWithSignature(\"_setInterestRateModel(address)\", newInterestRateModel)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Delegates execution to the implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToImplementation(bytes memory data) public returns (bytes memory) {\n return delegateTo(implementation, data);\n }\n\n /**\n * @notice Delegates execution to an implementation contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * There are an additional 2 prefix uints from the wrapper returndata, which we ignore since we make an extra hop.\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateToViewImplementation(bytes memory data) public view returns (bytes memory) {\n (bool success, bytes memory returnData) = address(this).staticcall(\n abi.encodeWithSignature(\"delegateToImplementation(bytes)\", data)\n );\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize())\n }\n }\n return abi.decode(returnData, (bytes));\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view override returns (uint) {\n bytes memory data = delegateToViewImplementation(\n abi.encodeWithSignature(\"borrowBalanceStored(address)\", account)\n );\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() public view override returns (uint) {\n bytes memory data = delegateToViewImplementation(abi.encodeWithSignature(\"exchangeRateStored()\"));\n return abi.decode(data, (uint));\n }\n\n /**\n * @notice Internal method to delegate execution to another contract\n * @dev It returns to the external caller whatever the implementation returns or forwards reverts\n * @param callee The contract to delegatecall\n * @param data The raw data to delegatecall\n * @return The returned bytes from the delegatecall\n */\n function delegateTo(address callee, bytes memory data) internal returns (bytes memory) {\n (bool success, bytes memory returnData) = callee.delegatecall(data);\n assembly {\n if eq(success, 0) {\n revert(add(returnData, 0x20), returndatasize())\n }\n }\n return returnData;\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBep20Immutable.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VBep20 } from \"./VBep20.sol\";\n\n/**\n * @title Venus's VBep20Immutable Contract\n * @notice VTokens which wrap an EIP-20 underlying and are immutable\n * @author Venus\n */\ncontract VBep20Immutable is VBep20 {\n /**\n * @notice Construct a new money market\n * @param underlying_ The address of the underlying asset\n * @param comptroller_ The address of the comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n */\n constructor(\n address underlying_,\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n // Initialize the market\n initialize(\n underlying_,\n comptroller_,\n interestRateModel_,\n initialExchangeRateMantissa_,\n name_,\n symbol_,\n decimals_\n );\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n}\n" + }, + "contracts/Tokens/VTokens/VBNB.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VToken } from \"./VToken.sol\";\n\n/**\n * @title Venus's vBNB Contract\n * @notice vToken which wraps BNB\n * @author Venus\n */\ncontract VBNB is VToken {\n /**\n * @notice Construct a new vBNB money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ BEP-20 name of this token\n * @param symbol_ BEP-20 symbol of this token\n * @param decimals_ BEP-20 decimal precision of this token\n * @param admin_ Address of the administrator of this token\n */\n constructor(\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_,\n address payable admin_\n ) {\n // Creator of the contract is admin during initialization\n admin = payable(msg.sender);\n\n initialize(comptroller_, interestRateModel_, initialExchangeRateMantissa_, name_, symbol_, decimals_);\n\n // Set the proper admin now that initialization is done\n admin = admin_;\n }\n\n /**\n * @notice Send BNB to VBNB to mint\n */\n receive() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /*** User Interface ***/\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Reverts upon any failure\n */\n // @custom:event Emits Transfer event\n // @custom:event Emits Mint event\n function mint() external payable {\n (uint err, ) = mintInternal(msg.value);\n requireNoError(err, \"mint failed\");\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for the underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeem(uint redeemTokens) external returns (uint) {\n return redeemInternal(msg.sender, payable(msg.sender), redeemTokens);\n }\n\n /**\n * @notice Sender redeems vTokens in exchange for a specified amount of underlying asset\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemAmount The amount of underlying to redeem\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Redeem event on success\n // @custom:event Emits Transfer event on success\n // @custom:event Emits RedeemFee when fee is charged by the treasury\n function redeemUnderlying(uint redeemAmount) external returns (uint) {\n return redeemUnderlyingInternal(msg.sender, payable(msg.sender), redeemAmount);\n }\n\n /**\n * @notice Sender borrows assets from the protocol to their own address\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Borrow event on success\n function borrow(uint borrowAmount) external returns (uint) {\n return borrowInternal(msg.sender, payable(msg.sender), borrowAmount);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @dev Reverts upon any failure\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrow() external payable {\n (uint err, ) = repayBorrowInternal(msg.value);\n requireNoError(err, \"repayBorrow failed\");\n }\n\n /**\n * @notice Sender repays a borrow belonging to borrower\n * @dev Reverts upon any failure\n * @param borrower The account with the debt being payed off\n */\n // @custom:event Emits RepayBorrow event on success\n function repayBorrowBehalf(address borrower) external payable {\n (uint err, ) = repayBorrowBehalfInternal(borrower, msg.value);\n requireNoError(err, \"repayBorrowBehalf failed\");\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @dev Reverts upon any failure\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n */\n // @custom:event Emit LiquidateBorrow event on success\n function liquidateBorrow(address borrower, VToken vTokenCollateral) external payable {\n (uint err, ) = liquidateBorrowInternal(borrower, msg.value, vTokenCollateral);\n requireNoError(err, \"liquidateBorrow failed\");\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Perform the actual transfer in, which is a no-op\n * @param from Address sending the BNB\n * @param amount Amount of BNB being sent\n * @return The actual amount of BNB transferred\n */\n function doTransferIn(address from, uint amount) internal override returns (uint) {\n // Sanity checks\n require(msg.sender == from, \"sender mismatch\");\n require(msg.value == amount, \"value mismatch\");\n return amount;\n }\n\n function doTransferOut(address payable to, uint amount) internal override {\n /* Send the BNB, with minimal gas and revert on failure */\n to.transfer(amount);\n }\n\n /**\n * @notice Gets balance of this contract in terms of BNB, before this message\n * @dev This excludes the value of the current message, if any\n * @return The quantity of BNB owned by this contract\n */\n function getCashPrior() internal view override returns (uint) {\n (MathError err, uint startingBalance) = subUInt(address(this).balance, msg.value);\n require(err == MathError.NO_ERROR, \"cash prior math error\");\n return startingBalance;\n }\n\n function requireNoError(uint errCode, string memory message) internal pure {\n if (errCode == uint(Error.NO_ERROR)) {\n return;\n }\n\n bytes memory fullMessage = new bytes(bytes(message).length + 5);\n uint i;\n\n for (i = 0; i < bytes(message).length; i++) {\n fullMessage[i] = bytes(message)[i];\n }\n\n fullMessage[i + 0] = bytes1(uint8(32));\n fullMessage[i + 1] = bytes1(uint8(40));\n fullMessage[i + 2] = bytes1(uint8(48 + (errCode / 10)));\n fullMessage[i + 3] = bytes1(uint8(48 + (errCode % 10)));\n fullMessage[i + 4] = bytes1(uint8(41));\n\n require(errCode == uint(Error.NO_ERROR), string(fullMessage));\n }\n}\n" + }, + "contracts/Tokens/VTokens/VToken.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { IAccessControlManagerV8 } from \"@venusprotocol/governance-contracts/contracts/Governance/IAccessControlManagerV8.sol\";\nimport { IProtocolShareReserve } from \"../../external/IProtocolShareReserve.sol\";\nimport { ComptrollerInterface, IComptroller } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { TokenErrorReporter } from \"../../Utils/ErrorReporter.sol\";\nimport { Exponential } from \"../../Utils/Exponential.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\nimport { VTokenInterface } from \"./VTokenInterfaces.sol\";\nimport { MANTISSA_ONE } from \"@venusprotocol/solidity-utilities/contracts/constants.sol\";\n\n/**\n * @title Venus's vToken Contract\n * @notice Abstract base for vTokens\n * @author Venus\n */\nabstract contract VToken is VTokenInterface, Exponential, TokenErrorReporter {\n struct MintLocalVars {\n MathError mathErr;\n uint exchangeRateMantissa;\n uint mintTokens;\n uint totalSupplyNew;\n uint accountTokensNew;\n uint actualMintAmount;\n }\n\n struct RedeemLocalVars {\n MathError mathErr;\n uint exchangeRateMantissa;\n uint redeemTokens;\n uint redeemAmount;\n uint totalSupplyNew;\n uint accountTokensNew;\n }\n\n struct BorrowLocalVars {\n MathError mathErr;\n uint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n }\n\n struct RepayBorrowLocalVars {\n Error err;\n MathError mathErr;\n uint repayAmount;\n uint borrowerIndex;\n uint accountBorrows;\n uint accountBorrowsNew;\n uint totalBorrowsNew;\n uint actualRepayAmount;\n }\n\n /*** Reentrancy Guard ***/\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n */\n modifier nonReentrant() {\n require(_notEntered, \"re-entered\");\n _notEntered = false;\n _;\n _notEntered = true; // get a gas-refund post-Istanbul\n }\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n // @custom:event Emits Transfer event\n function transfer(address dst, uint256 amount) external override nonReentrant returns (bool) {\n return transferTokens(msg.sender, msg.sender, dst, amount) == uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param amount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n // @custom:event Emits Transfer event\n function transferFrom(address src, address dst, uint256 amount) external override nonReentrant returns (bool) {\n return transferTokens(msg.sender, src, dst, amount) == uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)\n * @param spender The address of the account which may transfer tokens\n * @param amount The number of tokens that are approved (type(uint256).max means infinite)\n * @return Whether or not the approval succeeded\n */\n // @custom:event Emits Approval event on successful approve\n function approve(address spender, uint256 amount) external override returns (bool) {\n transferAllowances[msg.sender][spender] = amount;\n emit Approval(msg.sender, spender, amount);\n return true;\n }\n\n /**\n * @notice Get the underlying balance of the `owner`\n * @dev This also accrues interest in a transaction\n * @param owner The address of the account to query\n * @return The amount of underlying owned by `owner`\n */\n function balanceOfUnderlying(address owner) external override returns (uint) {\n Exp memory exchangeRate = Exp({ mantissa: exchangeRateCurrent() });\n (MathError mErr, uint balance) = mulScalarTruncate(exchangeRate, accountTokens[owner]);\n ensureNoMathError(mErr);\n return balance;\n }\n\n /**\n * @notice Returns the current total borrows plus accrued interest\n * @return The total borrows with interest\n */\n function totalBorrowsCurrent() external override nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return totalBorrows;\n }\n\n /**\n * @notice Accrue interest to updated borrowIndex and then calculate account's borrow balance using the updated borrowIndex\n * @param account The address whose balance should be calculated after updating borrowIndex\n * @return The calculated balance\n */\n function borrowBalanceCurrent(address account) external override nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return borrowBalanceStored(account);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Will fail unless called by another vToken during the process of liquidation.\n * Its absolutely critical to use msg.sender as the borrowed vToken and not a parameter.\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits Transfer event\n function seize(\n address liquidator,\n address borrower,\n uint seizeTokens\n ) external override nonReentrant returns (uint) {\n return seizeInternal(msg.sender, liquidator, borrower, seizeTokens);\n }\n\n /**\n * @notice Begins transfer of admin rights. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @dev Admin function to begin change of admin. The newPendingAdmin must call `_acceptAdmin` to finalize the transfer.\n * @param newPendingAdmin New pending admin.\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewPendingAdmin event with old and new admin addresses\n function _setPendingAdmin(address payable newPendingAdmin) external override returns (uint) {\n // Check caller = admin\n ensureAdmin(msg.sender);\n\n // Save current value, if any, for inclusion in log\n address oldPendingAdmin = pendingAdmin;\n\n // Store pendingAdmin with value newPendingAdmin\n pendingAdmin = newPendingAdmin;\n\n // Emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin)\n emit NewPendingAdmin(oldPendingAdmin, newPendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accepts transfer of admin rights. msg.sender must be pendingAdmin\n * @dev Admin function for pending admin to accept role and update admin\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewAdmin event on successful acceptance\n // @custom:event Emits NewPendingAdmin event with null new pending admin\n function _acceptAdmin() external override returns (uint) {\n // Check caller is pendingAdmin\n if (msg.sender != pendingAdmin) {\n return fail(Error.UNAUTHORIZED, FailureInfo.ACCEPT_ADMIN_PENDING_ADMIN_CHECK);\n }\n\n // Save current values for inclusion in log\n address oldAdmin = admin;\n address oldPendingAdmin = pendingAdmin;\n\n // Store admin with value pendingAdmin\n admin = pendingAdmin;\n\n // Clear the pending value\n pendingAdmin = payable(address(0));\n\n emit NewAdmin(oldAdmin, admin);\n emit NewPendingAdmin(oldPendingAdmin, pendingAdmin);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice accrues interest and sets a new reserve factor for the protocol using `_setReserveFactorFresh`\n * @dev Governor function to accrue interest and set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewReserveFactor event\n function _setReserveFactor(uint newReserveFactorMantissa_) external override nonReentrant returns (uint) {\n ensureAllowed(\"_setReserveFactor(uint256)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reserve factor change failed.\n return fail(Error(error), FailureInfo.SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED);\n }\n\n // _setReserveFactorFresh emits reserve-factor-specific logs on errors, so we don't need to.\n return _setReserveFactorFresh(newReserveFactorMantissa_);\n }\n\n /**\n * @notice Sets the address of the access control manager of this contract\n * @dev Admin function to set the access control address\n * @param newAccessControlManagerAddress New address for the access control\n * @return uint 0=success, otherwise will revert\n */\n function setAccessControlManager(address newAccessControlManagerAddress) external returns (uint) {\n // Check caller is admin\n ensureAdmin(msg.sender);\n\n ensureNonZeroAddress(newAccessControlManagerAddress);\n\n emit NewAccessControlManager(accessControlManager, newAccessControlManagerAddress);\n accessControlManager = newAccessControlManagerAddress;\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and reduces reserves by transferring to protocol share reserve\n * @param reduceAmount_ Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits ReservesReduced event\n function _reduceReserves(uint reduceAmount_) external virtual override nonReentrant returns (uint) {\n ensureAllowed(\"_reduceReserves(uint256)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.REDUCE_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n\n // If reserves were reduced in accrueInterest\n if (reduceReservesBlockNumber == block.number) return (uint(Error.NO_ERROR));\n // _reduceReservesFresh emits reserve-reduction-specific logs on errors, so we don't need to.\n return _reduceReservesFresh(reduceAmount_);\n }\n\n /**\n * @notice Get the current allowance from `owner` for `spender`\n * @param owner The address of the account which owns the tokens to be spent\n * @param spender The address of the account which may transfer tokens\n * @return The number of tokens allowed to be spent (type(uint256).max means infinite)\n */\n function allowance(address owner, address spender) external view override returns (uint256) {\n return transferAllowances[owner][spender];\n }\n\n /**\n * @notice Get the token balance of the `owner`\n * @param owner The address of the account to query\n * @return The number of tokens owned by `owner`\n */\n function balanceOf(address owner) external view override returns (uint256) {\n return accountTokens[owner];\n }\n\n /**\n * @notice Get a snapshot of the account's balances, and the cached exchange rate\n * @dev This is used by comptroller to more efficiently perform liquidity checks.\n * @param account Address of the account to snapshot\n * @return (possible error, token balance, borrow balance, exchange rate mantissa)\n */\n function getAccountSnapshot(address account) external view override returns (uint, uint, uint, uint) {\n uint borrowBalance;\n uint exchangeRateMantissa;\n\n MathError mErr;\n\n (mErr, borrowBalance) = borrowBalanceStoredInternal(account);\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0, 0);\n }\n\n (mErr, exchangeRateMantissa) = exchangeRateStoredInternal();\n if (mErr != MathError.NO_ERROR) {\n return (uint(Error.MATH_ERROR), 0, 0, 0);\n }\n\n return (uint(Error.NO_ERROR), accountTokens[account], borrowBalance, exchangeRateMantissa);\n }\n\n /**\n * @notice Returns the current per-block supply interest rate for this vToken\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\n * @return The supply interest rate per block, scaled by 1e18\n */\n function supplyRatePerBlock() external view override returns (uint) {\n return\n interestRateModel.getSupplyRate(\n _getCashPriorWithFlashLoan(),\n totalBorrows,\n totalReserves,\n reserveFactorMantissa\n );\n }\n\n /**\n * @notice Returns the current per-block borrow interest rate for this vToken\n * @dev The calculation includes `flashLoanAmount` in the cash balance to account for active flash loans.\n * @return The borrow interest rate per block, scaled by 1e18\n */\n function borrowRatePerBlock() external view override returns (uint) {\n return interestRateModel.getBorrowRate(_getCashPriorWithFlashLoan(), totalBorrows, totalReserves);\n }\n\n /**\n * @notice Get cash balance of this vToken in the underlying asset\n * @return The quantity of underlying asset owned by this contract\n */\n function getCash() external view override returns (uint) {\n return getCashPrior();\n }\n\n /**\n * @notice Governance function to set new threshold of block difference after which funds will be sent to the protocol share reserve\n * @param newReduceReservesBlockDelta_ block difference value\n */\n function setReduceReservesBlockDelta(uint256 newReduceReservesBlockDelta_) external {\n require(newReduceReservesBlockDelta_ > 0, \"Invalid Input\");\n ensureAllowed(\"setReduceReservesBlockDelta(uint256)\");\n emit NewReduceReservesBlockDelta(reduceReservesBlockDelta, newReduceReservesBlockDelta_);\n reduceReservesBlockDelta = newReduceReservesBlockDelta_;\n }\n\n /**\n * @notice Sets protocol share reserve contract address\n * @param protcolShareReserve_ The address of protocol share reserve contract\n */\n function setProtocolShareReserve(address payable protcolShareReserve_) external {\n // Check caller is admin\n ensureAdmin(msg.sender);\n ensureNonZeroAddress(protcolShareReserve_);\n emit NewProtocolShareReserve(protocolShareReserve, protcolShareReserve_);\n protocolShareReserve = protcolShareReserve_;\n }\n\n /**\n * @notice Transfers the underlying asset to the specified address for flash loan purposes.\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\n * asset by calling the `doTransferOut` internal function.\n * - The caller must be the Comptroller contract.\n * - Sets the flashLoanAmount to track the borrowed amount during the flash loan process.\n * @param to The address to which the underlying asset is to be transferred.\n * @param amount The amount of the underlying asset to transfer.\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\n * @custom:error FlashLoanAlreadyActive is thrown if there is already an active flash loan.\n * @custom:error InsufficientCash is thrown when the vToken does not have enough cash to lend\n * @custom:event Emits TransferOutUnderlyingFlashLoan event on successful transfer of amount to receiver\n */\n function transferOutUnderlyingFlashLoan(address payable to, uint256 amount) external nonReentrant {\n if (msg.sender != address(comptroller)) {\n revert InvalidComptroller();\n }\n\n if (flashLoanAmount > 0) {\n revert FlashLoanAlreadyActive();\n }\n\n if (getCashPrior() < amount) {\n revert InsufficientCash();\n }\n flashLoanAmount = amount;\n doTransferOut(to, amount);\n emit TransferOutUnderlyingFlashLoan(underlying, to, amount);\n }\n\n /**\n * @notice Transfers the underlying asset from the specified address during flash loan repayment.\n * @dev Can only be called by the Comptroller contract. This function performs the actual transfer of the underlying\n * asset by calling the `doTransferIn` internal function and handles protocol fee distribution.\n * - The caller must be the Comptroller contract.\n * - Transfers the protocol fee to the protocol share reserve.\n * - Resets the flashLoanAmount to 0 to complete the flash loan cycle.\n * @param from The address from which the underlying asset is to be transferred.\n * @param repaymentAmount The amount of the underlying asset being repaid by the receiver.\n * @param totalFee The total fee amount for the flash loan.\n * @param protocolFee The protocol fee amount to be transferred to the protocol share reserve.\n * @return actualAmountTransferred The actual amount transferred in from the receiver.\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\n * @custom:error InsufficientRepayment is thrown when the repayment amount is insufficient to cover the total fee\n * @custom:event Emits TransferInUnderlyingFlashLoan event on successful transfer of amount from the receiver to the vToken\n */\n function transferInUnderlyingFlashLoan(\n address payable from,\n uint256 repaymentAmount,\n uint256 totalFee,\n uint256 protocolFee\n ) external nonReentrant returns (uint256) {\n if (msg.sender != address(comptroller)) {\n revert InvalidComptroller();\n }\n\n uint256 actualAmountTransferred = doTransferIn(from, repaymentAmount);\n\n if (actualAmountTransferred < totalFee) {\n revert InsufficientRepayment(actualAmountTransferred, totalFee);\n }\n\n // Transfer protocol fee to protocol share reserve\n doTransferOut(protocolShareReserve, protocolFee);\n\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.FLASHLOAN\n );\n\n // Reset flashLoanAmount to complete the flash loan cycle\n flashLoanAmount = 0;\n\n emit TransferInUnderlyingFlashLoan(underlying, from, actualAmountTransferred, totalFee, protocolFee);\n return actualAmountTransferred;\n }\n\n /**\n * @notice Sets flash loan status for the market\n * @param enabled True to enable flash loans, false to disable\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n * @custom:access Only Governance\n * @custom:event Emits FlashLoanStatusChanged event on success\n */\n function setFlashLoanEnabled(bool enabled) external returns (uint256) {\n ensureAllowed(\"setFlashLoanEnabled(bool)\");\n\n if (isFlashLoanEnabled != enabled) {\n emit FlashLoanStatusChanged(isFlashLoanEnabled, enabled);\n isFlashLoanEnabled = enabled;\n }\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Update flashLoan fee mantissa\n * @param flashLoanFeeMantissa_ FlashLoan fee, scaled by 1e18\n * @param flashLoanProtocolShare_ FlashLoan protocol fee share, transferred to protocol share reserve\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n * @custom:access Only Governance\n * @custom:error FlashLoanFeeTooHigh is thrown when flash loan fee exceeds maximum allowed\n * @custom:error FlashLoanProtocolShareTooHigh is thrown when flash loan fee protocol share exceeds maximum allowed\n * @custom:event Emits FlashLoanFeeUpdated event on success\n */\n function setFlashLoanFeeMantissa(\n uint256 flashLoanFeeMantissa_,\n uint256 flashLoanProtocolShare_\n ) external returns (uint256) {\n ensureAllowed(\"setFlashLoanFeeMantissa(uint256,uint256)\");\n\n if (flashLoanFeeMantissa_ > MANTISSA_ONE) {\n revert FlashLoanFeeTooHigh(flashLoanFeeMantissa_, MANTISSA_ONE);\n }\n\n if (flashLoanProtocolShare_ > MANTISSA_ONE) {\n revert FlashLoanProtocolShareTooHigh(flashLoanProtocolShare_, MANTISSA_ONE);\n }\n\n // Only proceed if values are changing\n if (\n flashLoanFeeMantissa != flashLoanFeeMantissa_ || flashLoanProtocolShareMantissa != flashLoanProtocolShare_\n ) {\n emit FlashLoanFeeUpdated(\n flashLoanFeeMantissa,\n flashLoanFeeMantissa_,\n flashLoanProtocolShareMantissa,\n flashLoanProtocolShare_\n );\n\n flashLoanFeeMantissa = flashLoanFeeMantissa_;\n flashLoanProtocolShareMantissa = flashLoanProtocolShare_;\n }\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Initialize the money market\n * @param comptroller_ The address of the Comptroller\n * @param interestRateModel_ The address of the interest rate model\n * @param initialExchangeRateMantissa_ The initial exchange rate, scaled by 1e18\n * @param name_ EIP-20 name of this token\n * @param symbol_ EIP-20 symbol of this token\n * @param decimals_ EIP-20 decimal precision of this token\n */\n function initialize(\n ComptrollerInterface comptroller_,\n InterestRateModelV8 interestRateModel_,\n uint initialExchangeRateMantissa_,\n string memory name_,\n string memory symbol_,\n uint8 decimals_\n ) public {\n ensureAdmin(msg.sender);\n require(accrualBlockNumber == 0 && borrowIndex == 0, \"market may only be initialized once\");\n\n // Set initial exchange rate\n initialExchangeRateMantissa = initialExchangeRateMantissa_;\n require(initialExchangeRateMantissa > 0, \"initial exchange rate must be greater than zero.\");\n\n // Set the comptroller\n uint err = _setComptroller(comptroller_);\n require(err == uint(Error.NO_ERROR), \"setting comptroller failed\");\n\n // Initialize block number and borrow index (block number mocks depend on comptroller being set)\n accrualBlockNumber = block.number;\n borrowIndex = mantissaOne;\n\n // Set the interest rate model (depends on block number / borrow index)\n err = _setInterestRateModelFresh(interestRateModel_);\n require(err == uint(Error.NO_ERROR), \"setting interest rate model failed\");\n\n name = name_;\n symbol = symbol_;\n decimals = decimals_;\n\n // The counter starts true to prevent changing it from zero to non-zero (i.e. smaller cost/refund)\n _notEntered = true;\n }\n\n /**\n * @notice Accrue interest then return the up-to-date exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateCurrent() public override nonReentrant returns (uint) {\n require(accrueInterest() == uint(Error.NO_ERROR), \"accrue interest failed\");\n return exchangeRateStored();\n }\n\n /**\n * @notice Applies accrued interest to total borrows and reserves\n * @dev This calculates interest accrued from the last checkpointed block\n * up to the current block and writes new checkpoint to storage and\n * reduce spread reserves to protocol share reserve\n * if currentBlock - reduceReservesBlockNumber >= blockDelta\n */\n // @custom:event Emits AccrueInterest event\n function accrueInterest() public virtual override returns (uint) {\n /* Remember the initial block number */\n uint currentBlockNumber = block.number;\n uint accrualBlockNumberPrior = accrualBlockNumber;\n\n /* Short-circuit accumulating 0 interest */\n if (accrualBlockNumberPrior == currentBlockNumber) {\n return uint(Error.NO_ERROR);\n }\n\n /* Read the previous values out of storage */\n uint cashPrior = _getCashPriorWithFlashLoan();\n uint borrowsPrior = totalBorrows;\n uint reservesPrior = totalReserves;\n uint borrowIndexPrior = borrowIndex;\n\n /* Calculate the current borrow interest rate */\n uint borrowRateMantissa = interestRateModel.getBorrowRate(cashPrior, borrowsPrior, reservesPrior);\n require(borrowRateMantissa <= borrowRateMaxMantissa, \"borrow rate is absurdly high\");\n\n /* Calculate the number of blocks elapsed since the last accrual */\n (MathError mathErr, uint blockDelta) = subUInt(currentBlockNumber, accrualBlockNumberPrior);\n ensureNoMathError(mathErr);\n\n /*\n * Calculate the interest accumulated into borrows and reserves and the new index:\n * simpleInterestFactor = borrowRate * blockDelta\n * interestAccumulated = simpleInterestFactor * totalBorrows\n * totalBorrowsNew = interestAccumulated + totalBorrows\n * totalReservesNew = interestAccumulated * reserveFactor + totalReserves\n * borrowIndexNew = simpleInterestFactor * borrowIndex + borrowIndex\n */\n\n Exp memory simpleInterestFactor;\n uint interestAccumulated;\n uint totalBorrowsNew;\n uint totalReservesNew;\n uint borrowIndexNew;\n\n (mathErr, simpleInterestFactor) = mulScalar(Exp({ mantissa: borrowRateMantissa }), blockDelta);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, interestAccumulated) = mulScalarTruncate(simpleInterestFactor, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalBorrowsNew) = addUInt(interestAccumulated, borrowsPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, totalReservesNew) = mulScalarTruncateAddUInt(\n Exp({ mantissa: reserveFactorMantissa }),\n interestAccumulated,\n reservesPrior\n );\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n (mathErr, borrowIndexNew) = mulScalarTruncateAddUInt(simpleInterestFactor, borrowIndexPrior, borrowIndexPrior);\n if (mathErr != MathError.NO_ERROR) {\n return\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n uint(mathErr)\n );\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accrualBlockNumber = currentBlockNumber;\n borrowIndex = borrowIndexNew;\n totalBorrows = totalBorrowsNew;\n totalReserves = totalReservesNew;\n\n (mathErr, blockDelta) = subUInt(currentBlockNumber, reduceReservesBlockNumber);\n ensureNoMathError(mathErr);\n if (blockDelta >= reduceReservesBlockDelta) {\n reduceReservesBlockNumber = currentBlockNumber;\n uint actualCash = getCashPrior();\n if (actualCash < totalReservesNew) {\n _reduceReservesFresh(actualCash);\n } else {\n _reduceReservesFresh(totalReservesNew);\n }\n }\n\n /* We emit an AccrueInterest event */\n emit AccrueInterest(cashPrior, interestAccumulated, borrowIndexNew, totalBorrowsNew);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets a new comptroller for the market\n * @dev Admin function to set a new comptroller\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // @custom:event Emits NewComptroller event\n function _setComptroller(ComptrollerInterface newComptroller) public override returns (uint) {\n // Check caller is admin\n ensureAdmin(msg.sender);\n\n // Ensure invoke comptroller.isComptroller() returns true\n require(newComptroller.isComptroller(), \"marker method returned false\");\n\n // Emit NewComptroller(oldComptroller, newComptroller)\n emit NewComptroller(comptroller, newComptroller);\n\n // Set market's comptroller to newComptroller\n comptroller = newComptroller;\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and updates the interest rate model using _setInterestRateModelFresh\n * @dev Governance function to accrue interest and update the interest rate model\n * @param newInterestRateModel_ The new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel_) public override returns (uint) {\n ensureAllowed(\"_setInterestRateModel(address)\");\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted change of interest rate model failed\n return fail(Error(error), FailureInfo.SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED);\n }\n\n // _setInterestRateModelFresh emits interest-rate-model-update-specific logs on errors, so we don't need to.\n return _setInterestRateModelFresh(newInterestRateModel_);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the VToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Calculated exchange rate scaled by 1e18\n */\n function exchangeRateStored() public view override returns (uint) {\n (MathError err, uint result) = exchangeRateStoredInternal();\n ensureNoMathError(err);\n return result;\n }\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return The calculated balance\n */\n function borrowBalanceStored(address account) public view override returns (uint) {\n (MathError err, uint result) = borrowBalanceStoredInternal(account);\n ensureNoMathError(err);\n return result;\n }\n\n /**\n * @notice Opens a debt position for the borrower as part of flash loan repayment\n * @dev This function is specifically called during flash loan operations when the repayment\n * is insufficient to cover the full borrowed amount plus fees. It creates a debt position\n * for the unpaid balance. The function checks if the borrow is allowed, accrues interest,\n * and updates the borrower's balance. It also emits a Borrow event and calls the\n * comptroller's borrowVerify function. It reverts if the borrow is not allowed or\n * if the market's block number is not current.\n * @param borrower The address of the borrower who will have the debt position created\n * @param borrowAmount The amount of underlying asset that becomes debt (unpaid flash loan balance)\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n * @custom:error InvalidComptroller is thrown if the caller is not the Comptroller.\n */\n function flashLoanDebtPosition(address borrower, uint borrowAmount) external nonReentrant returns (uint256) {\n // Reverts if the caller is not the comptroller\n if (msg.sender != address(comptroller)) {\n revert InvalidComptroller();\n }\n\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors.\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\n }\n\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n return borrowFresh(borrower, payable(address(0)), borrowAmount, false);\n }\n\n /**\n * @notice Calculates the total fee and protocol fee for a flash loan..\n * @param amount The amount of the flash loan.\n * @return totalFee The total fee for the flash loan.\n * @return protocolFee The portion of the total fee allocated to the protocol.\n */\n function calculateFlashLoanFee(uint256 amount) public view returns (uint256, uint256) {\n MathError mErr;\n uint256 totalFee;\n uint256 protocolFee;\n\n (mErr, totalFee) = mulScalarTruncate(Exp({ mantissa: amount }), flashLoanFeeMantissa);\n ensureNoMathError(mErr);\n\n (mErr, protocolFee) = mulScalarTruncate(Exp({ mantissa: totalFee }), flashLoanProtocolShareMantissa);\n ensureNoMathError(mErr);\n\n return (totalFee, protocolFee);\n }\n\n /**\n * @notice Transfers `tokens` tokens from `src` to `dst` by `spender`\n * @dev Called by both `transfer` and `transferFrom` internally\n * @param spender The address of the account performing the transfer\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param tokens The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferTokens(address spender, address src, address dst, uint tokens) internal returns (uint) {\n /* Fail if transfer not allowed */\n uint allowed = comptroller.transferAllowed(address(this), src, dst, tokens);\n if (allowed != 0) {\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.TRANSFER_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Do not allow self-transfers */\n if (src == dst) {\n return fail(Error.BAD_INPUT, FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n /* Get the allowance, infinite for the account owner */\n uint startingAllowance = 0;\n if (spender == src) {\n startingAllowance = type(uint256).max;\n } else {\n startingAllowance = transferAllowances[src][spender];\n }\n\n /* Do the calculations, checking for {under,over}flow */\n MathError mathErr;\n uint allowanceNew;\n uint srvTokensNew;\n uint dstTokensNew;\n\n (mathErr, allowanceNew) = subUInt(startingAllowance, tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ALLOWED);\n }\n\n (mathErr, srvTokensNew) = subUInt(accountTokens[src], tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_NOT_ENOUGH);\n }\n\n (mathErr, dstTokensNew) = addUInt(accountTokens[dst], tokens);\n if (mathErr != MathError.NO_ERROR) {\n return fail(Error.MATH_ERROR, FailureInfo.TRANSFER_TOO_MUCH);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n accountTokens[src] = srvTokensNew;\n accountTokens[dst] = dstTokensNew;\n\n /* Eat some of the allowance (if necessary) */\n if (startingAllowance != type(uint256).max) {\n transferAllowances[src][spender] = allowanceNew;\n }\n\n /* We emit a Transfer event */\n emit Transfer(src, dst, tokens);\n\n comptroller.transferVerify(address(this), src, dst, tokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender supplies assets into the market and receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintInternal(uint mintAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mint failed\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\n }\n\n // mintFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n return mintFresh(msg.sender, mintAmount);\n }\n\n /**\n * @notice User supplies assets into the market and receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param minter The address of the account which is supplying the assets\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintFresh(address minter, uint mintAmount) internal returns (uint, uint) {\n /* Fail if mint not allowed */\n uint allowed = comptroller.mintAllowed(address(this), minter, mintAmount);\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\n }\n\n MintLocalVars memory vars;\n\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the minter and the mintAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n vars.actualMintAmount = doTransferIn(minter, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\n vars.actualMintAmount,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n /*\n * We calculate the new total supply of vTokens and minter token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[minter] + mintTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[minter], vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[minter] = vars.accountTokensNew;\n\n /* We emit a Mint event, and a Transfer event */\n emit Mint(minter, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\n emit Transfer(address(this), minter, vars.mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), minter, vars.actualMintAmount, vars.mintTokens);\n\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Sender supplies assets into the market and receiver receives vTokens in exchange\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param receiver The address of the account which is receiving the vTokens\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintBehalfInternal(address receiver, uint mintAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted mintBehalf failed\n return (fail(Error(error), FailureInfo.MINT_ACCRUE_INTEREST_FAILED), 0);\n }\n\n // mintBehalfFresh emits the actual Mint event if successful and logs on errors, so we don't need to\n return mintBehalfFresh(msg.sender, receiver, mintAmount);\n }\n\n /**\n * @notice Payer supplies assets into the market and receiver receives vTokens in exchange\n * @dev Assumes interest has already been accrued up to the current block\n * @param payer The address of the account which is paying the underlying token\n * @param receiver The address of the account which is receiving vToken\n * @param mintAmount The amount of the underlying asset to supply\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual mint amount.\n */\n function mintBehalfFresh(address payer, address receiver, uint mintAmount) internal returns (uint, uint) {\n ensureNonZeroAddress(receiver);\n /* Fail if mint not allowed */\n uint allowed = comptroller.mintAllowed(address(this), receiver, mintAmount);\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.MINT_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.MINT_FRESHNESS_CHECK), 0);\n }\n\n MintLocalVars memory vars;\n\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n if (vars.mathErr != MathError.NO_ERROR) {\n return (failOpaque(Error.MATH_ERROR, FailureInfo.MINT_EXCHANGE_RATE_READ_FAILED, uint(vars.mathErr)), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call `doTransferIn` for the payer and the mintAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * `doTransferIn` reverts if anything goes wrong, since we can't be sure if\n * side-effects occurred. The function returns the amount actually transferred,\n * in case of a fee. On success, the vToken holds an additional `actualMintAmount`\n * of cash.\n */\n vars.actualMintAmount = doTransferIn(payer, mintAmount);\n\n /*\n * We get the current exchange rate and calculate the number of vTokens to be minted:\n * mintTokens = actualMintAmount / exchangeRate\n */\n\n (vars.mathErr, vars.mintTokens) = divScalarByExpTruncate(\n vars.actualMintAmount,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n /*\n * We calculate the new total supply of vTokens and receiver token balance, checking for overflow:\n * totalSupplyNew = totalSupply + mintTokens\n * accountTokensNew = accountTokens[receiver] + mintTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = addUInt(totalSupply, vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountTokensNew) = addUInt(accountTokens[receiver], vars.mintTokens);\n ensureNoMathError(vars.mathErr);\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[receiver] = vars.accountTokensNew;\n\n /* We emit a MintBehalf event, and a Transfer event */\n emit MintBehalf(payer, receiver, vars.actualMintAmount, vars.mintTokens, vars.accountTokensNew);\n emit Transfer(address(this), receiver, vars.mintTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.mintVerify(address(this), receiver, vars.actualMintAmount, vars.mintTokens);\n\n return (uint(Error.NO_ERROR), vars.actualMintAmount);\n }\n\n /**\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the tokens\n * @param redeemTokens The number of vTokens to redeem into underlying\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemInternal(\n address redeemer,\n address payable receiver,\n uint redeemTokens\n ) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\n return redeemFresh(redeemer, receiver, redeemTokens, 0);\n }\n\n /**\n * @notice Sender redeems underlying assets on behalf of some other address. This function is only available\n * for senders, explicitly marked as delegates of the supplier using `comptroller.updateDelegate`\n * @dev Accrues interest whether or not the operation succeeds, unless reverted\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the tokens, if called by a delegate\n * @param redeemAmount The amount of underlying to receive from redeeming vTokens\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function redeemUnderlyingInternal(\n address redeemer,\n address payable receiver,\n uint redeemAmount\n ) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted redeem failed\n return fail(Error(error), FailureInfo.REDEEM_ACCRUE_INTEREST_FAILED);\n }\n\n // redeemFresh emits redeem-specific logs on errors, so we don't need to\n return redeemFresh(redeemer, receiver, 0, redeemAmount);\n }\n\n /**\n * @notice Redeemer redeems vTokens in exchange for the underlying assets, transferred to the receiver. Redeemer and receiver can be the same\n * address, or different addresses if the receiver was previously approved by the redeemer as a valid delegate (see MarketFacet.updateDelegate)\n * @dev Assumes interest has already been accrued up to the current block\n * @param redeemer The address of the account which is redeeming the tokens\n * @param receiver The receiver of the tokens\n * @param redeemTokensIn The number of vTokens to redeem into underlying (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @param redeemAmountIn The number of underlying tokens to receive from redeeming vTokens (only one of redeemTokensIn or redeemAmountIn may be non-zero)\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n // solhint-disable-next-line code-complexity\n function redeemFresh(\n address redeemer,\n address payable receiver,\n uint redeemTokensIn,\n uint redeemAmountIn\n ) internal returns (uint) {\n require(redeemTokensIn == 0 || redeemAmountIn == 0, \"one of redeemTokensIn or redeemAmountIn must be zero\");\n\n RedeemLocalVars memory vars;\n\n /* exchangeRate = invoke Exchange Rate Stored() */\n (vars.mathErr, vars.exchangeRateMantissa) = exchangeRateStoredInternal();\n ensureNoMathError(vars.mathErr);\n\n /* If redeemTokensIn > 0: */\n if (redeemTokensIn > 0) {\n /*\n * We calculate the exchange rate and the amount of underlying to be redeemed:\n * redeemTokens = redeemTokensIn\n * redeemAmount = redeemTokensIn x exchangeRateCurrent\n */\n vars.redeemTokens = redeemTokensIn;\n\n (vars.mathErr, vars.redeemAmount) = mulScalarTruncate(\n Exp({ mantissa: vars.exchangeRateMantissa }),\n redeemTokensIn\n );\n ensureNoMathError(vars.mathErr);\n } else {\n /*\n * We get the current exchange rate and calculate the amount to be redeemed:\n * redeemTokens = redeemAmountIn / exchangeRate\n * redeemAmount = redeemAmountIn\n */\n\n (vars.mathErr, vars.redeemTokens) = divScalarByExpTruncate(\n redeemAmountIn,\n Exp({ mantissa: vars.exchangeRateMantissa })\n );\n ensureNoMathError(vars.mathErr);\n\n vars.redeemAmount = redeemAmountIn;\n }\n\n /* Fail if redeem not allowed */\n uint allowed = comptroller.redeemAllowed(address(this), redeemer, vars.redeemTokens);\n if (allowed != 0) {\n revert(\"math error\");\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n revert(\"math error\");\n }\n\n /*\n * We calculate the new total supply and redeemer balance, checking for underflow:\n * totalSupplyNew = totalSupply - redeemTokens\n * accountTokensNew = accountTokens[redeemer] - redeemTokens\n */\n (vars.mathErr, vars.totalSupplyNew) = subUInt(totalSupply, vars.redeemTokens);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountTokensNew) = subUInt(accountTokens[redeemer], vars.redeemTokens);\n ensureNoMathError(vars.mathErr);\n\n /* Fail gracefully if protocol has insufficient cash */\n if (getCashPrior() < vars.redeemAmount) {\n revert(\"math error\");\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write previously calculated values into storage */\n totalSupply = vars.totalSupplyNew;\n accountTokens[redeemer] = vars.accountTokensNew;\n\n /*\n * We invoke doTransferOut for the receiver and the redeemAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken has redeemAmount less of cash.\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n\n uint feeAmount;\n uint remainedAmount;\n if (IComptroller(address(comptroller)).treasuryPercent() != 0) {\n (vars.mathErr, feeAmount) = mulUInt(\n vars.redeemAmount,\n IComptroller(address(comptroller)).treasuryPercent()\n );\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, feeAmount) = divUInt(feeAmount, MANTISSA_ONE);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, remainedAmount) = subUInt(vars.redeemAmount, feeAmount);\n ensureNoMathError(vars.mathErr);\n\n address payable treasuryAddress = payable(IComptroller(address(comptroller)).treasuryAddress());\n doTransferOut(treasuryAddress, feeAmount);\n\n emit RedeemFee(redeemer, feeAmount, vars.redeemTokens);\n } else {\n remainedAmount = vars.redeemAmount;\n }\n\n doTransferOut(receiver, remainedAmount);\n\n /* We emit a Transfer event, and a Redeem event */\n emit Transfer(redeemer, address(this), vars.redeemTokens);\n emit Redeem(redeemer, remainedAmount, vars.redeemTokens, vars.accountTokensNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.redeemVerify(address(this), redeemer, vars.redeemAmount, vars.redeemTokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Receiver gets the borrow on behalf of the borrower address\n * @param borrower The borrower, on behalf of whom to borrow\n * @param receiver The account that would receive the funds (can be the same as the borrower)\n * @param borrowAmount The amount of the underlying asset to borrow\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function borrowInternal(\n address borrower,\n address payable receiver,\n uint borrowAmount\n ) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return fail(Error(error), FailureInfo.BORROW_ACCRUE_INTEREST_FAILED);\n }\n\n // borrowFresh emits borrow-specific logs on errors, so we don't need to\n return borrowFresh(borrower, receiver, borrowAmount, true);\n }\n\n /**\n * @notice Receiver gets the borrow on behalf of the borrower address, controls whether to do the transfer\n * @dev Before calling this function, ensure that the interest has been accrued\n * @param borrower The borrower, on behalf of whom to borrow\n * @param receiver The account that would receive the funds (can be the same as the borrower)\n * @param borrowAmount The amount of the underlying asset to borrow\n * @param shouldTransfer Whether to call doTransferOut for the receiver\n * @return uint Returns 0 on success, otherwise revert (see ErrorReporter.sol for details).\n */\n function borrowFresh(\n address borrower,\n address payable receiver,\n uint borrowAmount,\n bool shouldTransfer\n ) internal returns (uint) {\n /* Revert if borrow not allowed */\n uint allowed = comptroller.borrowAllowed(address(this), borrower, borrowAmount);\n\n if (allowed != 0) {\n revert(\"math error\");\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n revert(\"math error\");\n }\n\n /* Revert if protocol has insufficient underlying cash */\n if (shouldTransfer && getCashPrior() < borrowAmount) {\n revert(\"math error\");\n }\n\n BorrowLocalVars memory vars;\n\n /*\n * We calculate the new borrower and total borrow balances, failing on overflow:\n * accountBorrowsNew = accountBorrows + borrowAmount\n * totalBorrowsNew = totalBorrows + borrowAmount\n */\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.accountBorrowsNew) = addUInt(vars.accountBorrows, borrowAmount);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.totalBorrowsNew) = addUInt(totalBorrows, borrowAmount);\n ensureNoMathError(vars.mathErr);\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n if (shouldTransfer) {\n /*\n * We invoke doTransferOut for the receiver and the borrowAmount.\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken borrowAmount less of cash.\n * doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n */\n doTransferOut(receiver, borrowAmount);\n }\n\n /* We emit a Borrow event */\n emit Borrow(borrower, borrowAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.borrowVerify(address(this), borrower, borrowAmount);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sender repays their own borrow\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowInternal(uint repayAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return (fail(Error(error), FailureInfo.REPAY_BORROW_ACCRUE_INTEREST_FAILED), 0);\n }\n\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n return repayBorrowFresh(msg.sender, msg.sender, repayAmount);\n }\n\n /**\n * @notice Sender repays a borrow belonging to another borrowing account\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowBehalfInternal(address borrower, uint repayAmount) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted borrow failed\n return (fail(Error(error), FailureInfo.REPAY_BEHALF_ACCRUE_INTEREST_FAILED), 0);\n }\n\n // repayBorrowFresh emits repay-borrow-specific logs on errors, so we don't need to\n return repayBorrowFresh(msg.sender, borrower, repayAmount);\n }\n\n /**\n * @notice Borrows are repaid by another user (possibly the borrower).\n * @param payer The account paying off the borrow\n * @param borrower The account with the debt being payed off\n * @param repayAmount The amount of undelrying tokens being returned\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function repayBorrowFresh(address payer, address borrower, uint repayAmount) internal returns (uint, uint) {\n /* Fail if repayBorrow not allowed */\n uint allowed = comptroller.repayBorrowAllowed(address(this), payer, borrower, repayAmount);\n if (allowed != 0) {\n return (\n failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.REPAY_BORROW_COMPTROLLER_REJECTION, allowed),\n 0\n );\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.REPAY_BORROW_FRESHNESS_CHECK), 0);\n }\n\n RepayBorrowLocalVars memory vars;\n\n /* We remember the original borrowerIndex for verification purposes */\n vars.borrowerIndex = accountBorrows[borrower].interestIndex;\n\n /* We fetch the amount the borrower owes, with accumulated interest */\n (vars.mathErr, vars.accountBorrows) = borrowBalanceStoredInternal(borrower);\n if (vars.mathErr != MathError.NO_ERROR) {\n return (\n failOpaque(\n Error.MATH_ERROR,\n FailureInfo.REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n uint(vars.mathErr)\n ),\n 0\n );\n }\n\n // caps the repayAmount to the actual owed amount\n vars.repayAmount = repayAmount >= vars.accountBorrows ? vars.accountBorrows : repayAmount;\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call doTransferIn for the payer and the repayAmount\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken holds an additional repayAmount of cash.\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n vars.actualRepayAmount = doTransferIn(payer, vars.repayAmount);\n\n /*\n * We calculate the new borrower and total borrow balances, failing on underflow:\n * accountBorrowsNew = accountBorrows - actualRepayAmount\n * totalBorrowsNew = totalBorrows - actualRepayAmount\n */\n (vars.mathErr, vars.accountBorrowsNew) = subUInt(vars.accountBorrows, vars.actualRepayAmount);\n ensureNoMathError(vars.mathErr);\n\n (vars.mathErr, vars.totalBorrowsNew) = subUInt(totalBorrows, vars.actualRepayAmount);\n ensureNoMathError(vars.mathErr);\n\n /* We write the previously calculated values into storage */\n accountBorrows[borrower].principal = vars.accountBorrowsNew;\n accountBorrows[borrower].interestIndex = borrowIndex;\n totalBorrows = vars.totalBorrowsNew;\n\n /* We emit a RepayBorrow event */\n emit RepayBorrow(payer, borrower, vars.actualRepayAmount, vars.accountBorrowsNew, vars.totalBorrowsNew);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.repayBorrowVerify(address(this), payer, borrower, vars.actualRepayAmount, vars.borrowerIndex);\n\n return (uint(Error.NO_ERROR), vars.actualRepayAmount);\n }\n\n /**\n * @notice The sender liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n function liquidateBorrowInternal(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) internal nonReentrant returns (uint, uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED), 0);\n }\n\n error = vTokenCollateral.accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but we still want to log the fact that an attempted liquidation failed\n return (fail(Error(error), FailureInfo.LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED), 0);\n }\n\n // liquidateBorrowFresh emits borrow-specific logs on errors, so we don't need to\n return liquidateBorrowFresh(msg.sender, borrower, repayAmount, vTokenCollateral);\n }\n\n /**\n * @notice The liquidator liquidates the borrowers collateral.\n * The collateral seized is transferred to the liquidator.\n * @param borrower The borrower of this vToken to be liquidated\n * @param liquidator The address repaying the borrow and seizing collateral\n * @param vTokenCollateral The market in which to seize collateral from the borrower\n * @param repayAmount The amount of the underlying borrowed asset to repay\n * @return (uint, uint) An error code (0=success, otherwise a failure, see ErrorReporter.sol), and the actual repayment amount.\n */\n // solhint-disable-next-line code-complexity\n function liquidateBorrowFresh(\n address liquidator,\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) internal returns (uint, uint) {\n /* Fail if liquidate not allowed */\n uint allowed = comptroller.liquidateBorrowAllowed(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n repayAmount\n );\n if (allowed != 0) {\n return (failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_COMPTROLLER_REJECTION, allowed), 0);\n }\n\n /* Verify market's block number equals current block number */\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_FRESHNESS_CHECK), 0);\n }\n\n /* Verify vTokenCollateral market's block number equals current block number */\n if (vTokenCollateral.accrualBlockNumber() != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.LIQUIDATE_COLLATERAL_FRESHNESS_CHECK), 0);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return (fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_LIQUIDATOR_IS_BORROWER), 0);\n }\n\n /* Fail if repayAmount = 0 */\n if (repayAmount == 0) {\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_ZERO), 0);\n }\n\n /* Fail if repayAmount = type(uint256).max */\n if (repayAmount == type(uint256).max) {\n return (fail(Error.INVALID_CLOSE_AMOUNT_REQUESTED, FailureInfo.LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX), 0);\n }\n\n /* Fail if repayBorrow fails */\n (uint repayBorrowError, uint actualRepayAmount) = repayBorrowFresh(liquidator, borrower, repayAmount);\n if (repayBorrowError != uint(Error.NO_ERROR)) {\n return (fail(Error(repayBorrowError), FailureInfo.LIQUIDATE_REPAY_BORROW_FRESH_FAILED), 0);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We calculate the number of collateral tokens that will be seized */\n (uint amountSeizeError, uint seizeTokens) = comptroller.liquidateCalculateSeizeTokens(\n borrower,\n address(this),\n address(vTokenCollateral),\n actualRepayAmount\n );\n\n require(amountSeizeError == uint(Error.NO_ERROR), \"LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED\");\n\n /* Revert if borrower collateral token balance < seizeTokens */\n require(vTokenCollateral.balanceOf(borrower) >= seizeTokens, \"LIQUIDATE_SEIZE_TOO_MUCH\");\n\n // If this is also the collateral, run seizeInternal to avoid re-entrancy, otherwise make an external call\n uint seizeError;\n if (address(vTokenCollateral) == address(this)) {\n seizeError = seizeInternal(address(this), liquidator, borrower, seizeTokens);\n } else {\n seizeError = vTokenCollateral.seize(liquidator, borrower, seizeTokens);\n }\n\n /* Revert if seize tokens fails (since we cannot be sure of side effects) */\n require(seizeError == uint(Error.NO_ERROR), \"token seizure failed\");\n\n /* We emit a LiquidateBorrow event */\n emit LiquidateBorrow(liquidator, borrower, actualRepayAmount, address(vTokenCollateral), seizeTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.liquidateBorrowVerify(\n address(this),\n address(vTokenCollateral),\n liquidator,\n borrower,\n actualRepayAmount,\n seizeTokens\n );\n\n return (uint(Error.NO_ERROR), actualRepayAmount);\n }\n\n /**\n * @notice Transfers collateral tokens (this market) to the liquidator.\n * @dev Called only during an in-kind liquidation, or by liquidateBorrow during the liquidation of another vToken.\n * Its absolutely critical to use msg.sender as the seizer vToken and not a parameter.\n * @param seizerToken The contract seizing the collateral (i.e. borrowed vToken)\n * @param liquidator The account receiving seized collateral\n * @param borrower The account having collateral seized\n * @param seizeTokens The number of vTokens to seize\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function seizeInternal(\n address seizerToken,\n address liquidator,\n address borrower,\n uint seizeTokens\n ) internal returns (uint) {\n /* Fail if seize not allowed */\n uint allowed = comptroller.seizeAllowed(address(this), seizerToken, liquidator, borrower, seizeTokens);\n if (allowed != 0) {\n return failOpaque(Error.COMPTROLLER_REJECTION, FailureInfo.LIQUIDATE_SEIZE_COMPTROLLER_REJECTION, allowed);\n }\n\n /* Fail if borrower = liquidator */\n if (borrower == liquidator) {\n return fail(Error.INVALID_ACCOUNT_PAIR, FailureInfo.LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER);\n }\n\n MathError mathErr;\n uint borrowerTokensNew;\n uint liquidatorTokensNew;\n\n /*\n * We calculate the new borrower and liquidator token balances, failing on underflow/overflow:\n * borrowerTokensNew = accountTokens[borrower] - seizeTokens\n * liquidatorTokensNew = accountTokens[liquidator] + seizeTokens\n */\n (mathErr, borrowerTokensNew) = subUInt(accountTokens[borrower], seizeTokens);\n if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED, uint(mathErr));\n }\n\n (mathErr, liquidatorTokensNew) = addUInt(accountTokens[liquidator], seizeTokens);\n if (mathErr != MathError.NO_ERROR) {\n return failOpaque(Error.MATH_ERROR, FailureInfo.LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED, uint(mathErr));\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /* We write the previously calculated values into storage */\n accountTokens[borrower] = borrowerTokensNew;\n accountTokens[liquidator] = liquidatorTokensNew;\n\n /* Emit a Transfer event */\n emit Transfer(borrower, liquidator, seizeTokens);\n\n /* We call the defense and prime accrue interest hook */\n comptroller.seizeVerify(address(this), seizerToken, liquidator, borrower, seizeTokens);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Sets a new reserve factor for the protocol (requires fresh interest accrual)\n * @dev Governance function to set a new reserve factor\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setReserveFactorFresh(uint newReserveFactorMantissa) internal returns (uint) {\n // Verify market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_RESERVE_FACTOR_FRESH_CHECK);\n }\n\n // Check newReserveFactor ≤ maxReserveFactor\n if (newReserveFactorMantissa > reserveFactorMaxMantissa) {\n return fail(Error.BAD_INPUT, FailureInfo.SET_RESERVE_FACTOR_BOUNDS_CHECK);\n }\n\n uint oldReserveFactorMantissa = reserveFactorMantissa;\n reserveFactorMantissa = newReserveFactorMantissa;\n\n emit NewReserveFactor(oldReserveFactorMantissa, newReserveFactorMantissa);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice Accrues interest and adds reserves by transferring from `msg.sender`\n * @param addAmount Amount of addition to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _addReservesInternal(uint addAmount) internal nonReentrant returns (uint) {\n uint error = accrueInterest();\n if (error != uint(Error.NO_ERROR)) {\n // accrueInterest emits logs on errors, but on top of that we want to log the fact that an attempted reduce reserves failed.\n return fail(Error(error), FailureInfo.ADD_RESERVES_ACCRUE_INTEREST_FAILED);\n }\n\n // _addReservesFresh emits reserve-addition-specific logs on errors, so we don't need to.\n (error, ) = _addReservesFresh(addAmount);\n return error;\n }\n\n /**\n * @notice Add reserves by transferring from caller\n * @dev Requires fresh interest accrual\n * @param addAmount Amount of addition to reserves\n * @return (uint, uint) An error code (0=success, otherwise a failure (see ErrorReporter.sol for details)) and the actual amount added, net token fees\n */\n function _addReservesFresh(uint addAmount) internal returns (uint, uint) {\n // totalReserves + actualAddAmount\n uint totalReservesNew;\n uint actualAddAmount;\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return (fail(Error.MARKET_NOT_FRESH, FailureInfo.ADD_RESERVES_FRESH_CHECK), actualAddAmount);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n /*\n * We call doTransferIn for the caller and the addAmount\n * Note: The vToken must handle variations between BEP-20 and BNB underlying.\n * On success, the vToken holds an additional addAmount of cash.\n * doTransferIn reverts if anything goes wrong, since we can't be sure if side effects occurred.\n * it returns the amount actually transferred, in case of a fee.\n */\n\n actualAddAmount = doTransferIn(msg.sender, addAmount);\n\n totalReservesNew = totalReserves + actualAddAmount;\n\n /* Revert on overflow */\n require(totalReservesNew >= totalReserves, \"add reserves unexpected overflow\");\n\n // Store reserves[n+1] = reserves[n] + actualAddAmount\n totalReserves = totalReservesNew;\n\n /* Emit NewReserves(admin, actualAddAmount, reserves[n+1]) */\n emit ReservesAdded(msg.sender, actualAddAmount, totalReservesNew);\n\n /* Return (NO_ERROR, actualAddAmount) */\n return (uint(Error.NO_ERROR), actualAddAmount);\n }\n\n /**\n * @notice Reduces reserves by transferring to protocol share reserve contract\n * @dev Requires fresh interest accrual\n * @param reduceAmount Amount of reduction to reserves\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _reduceReservesFresh(uint reduceAmount) internal virtual returns (uint) {\n if (reduceAmount == 0) {\n return uint(Error.NO_ERROR);\n }\n\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.REDUCE_RESERVES_FRESH_CHECK);\n }\n\n // Fail gracefully if protocol has insufficient underlying cash\n if (getCashPrior() < reduceAmount) {\n return fail(Error.TOKEN_INSUFFICIENT_CASH, FailureInfo.REDUCE_RESERVES_CASH_NOT_AVAILABLE);\n }\n\n // Check reduceAmount ≤ reserves[n] (totalReserves)\n if (reduceAmount > totalReserves) {\n return fail(Error.BAD_INPUT, FailureInfo.REDUCE_RESERVES_VALIDATION);\n }\n\n /////////////////////////\n // EFFECTS & INTERACTIONS\n // (No safe failures beyond this point)\n\n // Store reserves[n+1] = reserves[n] - reduceAmount\n totalReserves = totalReserves - reduceAmount;\n\n // doTransferOut reverts if anything goes wrong, since we can't be sure if side effects occurred.\n doTransferOut(protocolShareReserve, reduceAmount);\n\n IProtocolShareReserve(protocolShareReserve).updateAssetsState(\n address(comptroller),\n underlying,\n IProtocolShareReserve.IncomeType.SPREAD\n );\n\n emit ReservesReduced(protocolShareReserve, reduceAmount, totalReserves);\n\n return uint(Error.NO_ERROR);\n }\n\n /**\n * @notice updates the interest rate model (requires fresh interest accrual)\n * @dev Governance function to update the interest rate model\n * @param newInterestRateModel the new interest rate model to use\n * @return uint Returns 0 on success, otherwise returns a failure code (see ErrorReporter.sol for details).\n */\n function _setInterestRateModelFresh(InterestRateModelV8 newInterestRateModel) internal returns (uint) {\n // We fail gracefully unless market's block number equals current block number\n if (accrualBlockNumber != block.number) {\n return fail(Error.MARKET_NOT_FRESH, FailureInfo.SET_INTEREST_RATE_MODEL_FRESH_CHECK);\n }\n\n // Ensure invoke newInterestRateModel.isInterestRateModel() returns true\n require(newInterestRateModel.isInterestRateModel(), \"marker method returned false\");\n\n // Emit NewMarketInterestRateModel(oldInterestRateModel, newInterestRateModel)\n emit NewMarketInterestRateModel(interestRateModel, newInterestRateModel);\n\n // Set the interest rate model to newInterestRateModel\n interestRateModel = newInterestRateModel;\n\n return uint(Error.NO_ERROR);\n }\n\n /*** Safe Token ***/\n\n /**\n * @dev Performs a transfer in, reverting upon failure. Returns the amount actually transferred to the protocol, in case of a fee.\n * This may revert due to insufficient balance or insufficient allowance.\n */\n function doTransferIn(address from, uint amount) internal virtual returns (uint);\n\n /**\n * @dev Performs a transfer out, ideally returning an explanatory error code upon failure rather than reverting.\n * If caller has not called checked protocol's balance, may revert due to insufficient cash held in the contract.\n * If caller has checked protocol's balance, and verified it is >= amount, this should not revert in normal conditions.\n */\n function doTransferOut(address payable to, uint amount) internal virtual;\n\n /**\n * @notice Return the borrow balance of account based on stored data\n * @param account The address whose balance should be calculated\n * @return Tuple of error code and the calculated balance or 0 if error code is non-zero\n */\n function borrowBalanceStoredInternal(address account) internal view returns (MathError, uint) {\n /* Note: we do not assert that the market is up to date */\n MathError mathErr;\n uint principalTimesIndex;\n uint result;\n\n /* Get borrowBalance and borrowIndex */\n BorrowSnapshot storage borrowSnapshot = accountBorrows[account];\n\n /* If borrowBalance = 0 then borrowIndex is likely also 0.\n * Rather than failing the calculation with a division by 0, we immediately return 0 in this case.\n */\n if (borrowSnapshot.principal == 0) {\n return (MathError.NO_ERROR, 0);\n }\n\n /* Calculate new borrow balance using the interest index:\n * recentBorrowBalance = borrower.borrowBalance * market.borrowIndex / borrower.borrowIndex\n */\n (mathErr, principalTimesIndex) = mulUInt(borrowSnapshot.principal, borrowIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, result) = divUInt(principalTimesIndex, borrowSnapshot.interestIndex);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n return (MathError.NO_ERROR, result);\n }\n\n /**\n * @notice Calculates the exchange rate from the underlying to the vToken\n * @dev This function does not accrue interest before calculating the exchange rate\n * @return Tuple of error code and calculated exchange rate scaled by 1e18\n */\n function exchangeRateStoredInternal() internal view virtual returns (MathError, uint) {\n uint _totalSupply = totalSupply;\n if (_totalSupply == 0) {\n /*\n * If there are no tokens minted:\n * exchangeRate = initialExchangeRate\n */\n return (MathError.NO_ERROR, initialExchangeRateMantissa);\n } else {\n /*\n * Otherwise:\n * exchangeRate = (totalCash + totalBorrows + flashLoanAmount - totalReserves) / totalSupply\n */\n uint totalCash = _getCashPriorWithFlashLoan();\n uint cashPlusBorrowsMinusReserves;\n Exp memory exchangeRate;\n MathError mathErr;\n\n (mathErr, cashPlusBorrowsMinusReserves) = addThenSubUInt(totalCash, totalBorrows, totalReserves);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n (mathErr, exchangeRate) = getExp(cashPlusBorrowsMinusReserves, _totalSupply);\n if (mathErr != MathError.NO_ERROR) {\n return (mathErr, 0);\n }\n\n return (MathError.NO_ERROR, exchangeRate.mantissa);\n }\n }\n\n /**\n * @notice Gets balance of this contract including active flash loans\n * @return The quantity of underlying owned by this contract plus active flash loan amount\n */\n function _getCashPriorWithFlashLoan() internal view returns (uint) {\n return getCashPrior() + flashLoanAmount;\n }\n\n function ensureAllowed(string memory functionSig) private view {\n require(\n IAccessControlManagerV8(accessControlManager).isAllowedToCall(msg.sender, functionSig),\n \"access denied\"\n );\n }\n\n function ensureAdmin(address caller_) private view {\n require(caller_ == admin, \"Unauthorized\");\n }\n\n function ensureNoMathError(MathError mErr) private pure {\n require(mErr == MathError.NO_ERROR, \"math error\");\n }\n\n function ensureNonZeroAddress(address address_) private pure {\n require(address_ != address(0), \"zero address\");\n }\n\n /*** Safe Token ***/\n\n /**\n * @notice Gets balance of this contract in terms of the underlying\n * @dev This excludes the value of the current message, if any\n * @return The quantity of underlying owned by this contract\n */\n function getCashPrior() internal view virtual returns (uint);\n}\n" + }, + "contracts/Tokens/VTokens/VTokenInterfaces.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\nimport { ComptrollerInterface } from \"../../Comptroller/ComptrollerInterface.sol\";\nimport { InterestRateModelV8 } from \"../../InterestRateModels/InterestRateModelV8.sol\";\n\ncontract VTokenStorageBase {\n /**\n * @notice Container for borrow balance information\n * @member principal Total balance (with accrued interest), after applying the most recent balance-changing action\n * @member interestIndex Global borrowIndex as of the most recent balance-changing action\n */\n struct BorrowSnapshot {\n uint principal;\n uint interestIndex;\n }\n\n /**\n * @dev Guard variable for re-entrancy checks\n */\n bool internal _notEntered;\n\n /**\n * @notice EIP-20 token name for this token\n */\n string public name;\n\n /**\n * @notice EIP-20 token symbol for this token\n */\n string public symbol;\n\n /**\n * @notice EIP-20 token decimals for this token\n */\n uint8 public decimals;\n\n /**\n * @notice Maximum borrow rate that can ever be applied (.0005% / block)\n */\n\n uint internal constant borrowRateMaxMantissa = 0.0005e16;\n\n /**\n * @notice Maximum fraction of interest that can be set aside for reserves\n */\n uint internal constant reserveFactorMaxMantissa = 1e18;\n\n /**\n * @notice Administrator for this contract\n */\n address payable public admin;\n\n /**\n * @notice Pending administrator for this contract\n */\n address payable public pendingAdmin;\n\n /**\n * @notice Contract which oversees inter-vToken operations\n */\n ComptrollerInterface public comptroller;\n\n /**\n * @notice Model which tells what the current interest rate should be\n */\n InterestRateModelV8 public interestRateModel;\n\n /**\n * @notice Initial exchange rate used when minting the first VTokens (used when totalSupply = 0)\n */\n uint internal initialExchangeRateMantissa;\n\n /**\n * @notice Fraction of interest currently set aside for reserves\n */\n uint public reserveFactorMantissa;\n\n /**\n * @notice Block number that interest was last accrued at\n */\n uint public accrualBlockNumber;\n\n /**\n * @notice Accumulator of the total earned interest rate since the opening of the market\n */\n uint public borrowIndex;\n\n /**\n * @notice Total amount of outstanding borrows of the underlying in this market\n */\n uint public totalBorrows;\n\n /**\n * @notice Total amount of reserves of the underlying held in this market\n */\n uint public totalReserves;\n\n /**\n * @notice Total number of tokens in circulation\n */\n uint public totalSupply;\n\n /**\n * @notice Official record of token balances for each account\n */\n mapping(address => uint) internal accountTokens;\n\n /**\n * @notice Approved token transfer amounts on behalf of others\n */\n mapping(address => mapping(address => uint)) internal transferAllowances;\n\n /**\n * @notice Mapping of account addresses to outstanding borrow balances\n */\n mapping(address => BorrowSnapshot) internal accountBorrows;\n\n /**\n * @notice Underlying asset for this VToken\n */\n address public underlying;\n\n /**\n * @notice Implementation address for this contract\n */\n address public implementation;\n\n /**\n * @notice delta block after which reserves will be reduced\n */\n uint public reduceReservesBlockDelta;\n\n /**\n * @notice last block number at which reserves were reduced\n */\n uint public reduceReservesBlockNumber;\n\n /**\n * @notice address of protocol share reserve contract\n */\n address payable public protocolShareReserve;\n\n /**\n * @notice address of accessControlManager\n */\n\n address public accessControlManager;\n}\n\ncontract VTokenStorage is VTokenStorageBase {\n /**\n * @notice flashLoan is enabled for this market or not\n */\n bool public isFlashLoanEnabled;\n\n /**\n * @notice total fee percentage collected on flashLoan (scaled by 1e18)\n */\n uint256 public flashLoanFeeMantissa;\n\n /**\n * @notice fee percentage of flashLoan that goes to protocol (scaled by 1e18)\n */\n uint256 public flashLoanProtocolShareMantissa;\n\n /**\n * @notice Amount of flashLoan taken by the receiver\n * @dev This is used to track the amount of flashLoan taken to correctly calculate the exchange rate\n * during the flashLoan process. It is added to the total cash when calculating the exchange rate.\n */\n uint256 public flashLoanAmount;\n\n /**\n * @notice Tracked internal cash balance, immune to direct token transfers (donation attacks)\n * @dev Updated only via doTransferIn/doTransferOut. Must be initialized via sweepTokenAndSync() after upgrade.\n */\n uint256 public internalCash;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n\nabstract contract VTokenInterface is VTokenStorage {\n /**\n * @notice Indicator that this is a vToken contract (for inspection)\n */\n bool public constant isVToken = true;\n\n /*** Market Events ***/\n\n /**\n * @notice Event emitted when interest is accrued\n */\n event AccrueInterest(uint cashPrior, uint interestAccumulated, uint borrowIndex, uint totalBorrows);\n\n /**\n * @notice Event emitted when tokens are minted\n */\n event Mint(address minter, uint mintAmount, uint mintTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are minted behalf by payer to receiver\n */\n event MintBehalf(address payer, address receiver, uint mintAmount, uint mintTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are redeemed\n */\n event Redeem(address redeemer, uint redeemAmount, uint redeemTokens, uint256 totalSupply);\n\n /**\n * @notice Event emitted when tokens are redeemed and fee is transferred\n */\n event RedeemFee(address redeemer, uint feeAmount, uint redeemTokens);\n\n /**\n * @notice Event emitted when underlying is borrowed\n */\n event Borrow(address borrower, uint borrowAmount, uint accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is repaid\n */\n event RepayBorrow(address payer, address borrower, uint repayAmount, uint accountBorrows, uint totalBorrows);\n\n /**\n * @notice Event emitted when a borrow is liquidated\n */\n event LiquidateBorrow(\n address liquidator,\n address borrower,\n uint repayAmount,\n address vTokenCollateral,\n uint seizeTokens\n );\n\n /*** Admin Events ***/\n\n /**\n * @notice Event emitted when pendingAdmin is changed\n */\n event NewPendingAdmin(address oldPendingAdmin, address newPendingAdmin);\n\n /**\n * @notice Event emitted when pendingAdmin is accepted, which means admin has been updated\n */\n event NewAdmin(address oldAdmin, address newAdmin);\n\n /**\n * @notice Event emitted when comptroller is changed\n */\n event NewComptroller(ComptrollerInterface oldComptroller, ComptrollerInterface newComptroller);\n\n /**\n * @notice Event emitted when interestRateModel is changed\n */\n event NewMarketInterestRateModel(\n InterestRateModelV8 oldInterestRateModel,\n InterestRateModelV8 newInterestRateModel\n );\n\n /**\n * @notice Event emitted when the reserve factor is changed\n */\n event NewReserveFactor(uint oldReserveFactorMantissa, uint newReserveFactorMantissa);\n\n /**\n * @notice Event emitted when the reserves are added\n */\n event ReservesAdded(address benefactor, uint addAmount, uint newTotalReserves);\n\n /**\n * @notice Event emitted when the reserves are reduced\n */\n event ReservesReduced(address protocolShareReserve, uint reduceAmount, uint newTotalReserves);\n\n /**\n * @notice EIP20 Transfer event\n */\n event Transfer(address indexed from, address indexed to, uint amount);\n\n /**\n * @notice EIP20 Approval event\n */\n event Approval(address indexed owner, address indexed spender, uint amount);\n\n /**\n * @notice Event emitted when block delta for reduce reserves get updated\n */\n event NewReduceReservesBlockDelta(uint256 oldReduceReservesBlockDelta, uint256 newReduceReservesBlockDelta);\n\n /**\n * @notice Event emitted when address of ProtocolShareReserve contract get updated\n */\n event NewProtocolShareReserve(address indexed oldProtocolShareReserve, address indexed newProtocolShareReserve);\n\n /**\n * @notice Emitted when access control address is changed by admin\n */\n event NewAccessControlManager(address oldAccessControlAddress, address newAccessControlAddress);\n\n /**\n * @notice Event emitted when flashLoanEnabled status is changed\n */\n event FlashLoanStatusChanged(bool previousStatus, bool newStatus);\n\n /**\n * @notice Event emitted when asset is transferred to receiver\n */\n event TransferOutUnderlyingFlashLoan(address asset, address receiver, uint256 amount);\n\n /**\n * @notice Event emitted when asset is transferred from sender and verified\n */\n event TransferInUnderlyingFlashLoan(\n address indexed asset,\n address indexed sender,\n uint256 amount,\n uint256 totalFee,\n uint256 protocolFee\n );\n\n /**\n * @notice Event emitted when internalCash is synced with actual token balance\n */\n event CashSynced(uint256 oldInternalCash, uint256 newInternalCash);\n\n /**\n * @notice Event emitted when excess tokens are swept by admin\n */\n event TokenSwept(address indexed recipient, uint256 amount);\n\n /**\n * @notice Event emitted when flashLoan fee mantissa is updated\n */\n event FlashLoanFeeUpdated(\n uint256 oldFlashLoanFeeMantissa,\n uint256 newFlashLoanFeeMantissa,\n uint256 oldFlashLoanProtocolShare,\n uint256 newFlashLoanProtocolShare\n );\n\n // @notice Thrown when comptroller is not valid\n error InvalidComptroller();\n\n // @notice Thrown when there is already an active flashLoan\n error FlashLoanAlreadyActive();\n\n /// @notice Thrown when flash loan fee exceeds maximum allowed\n error FlashLoanFeeTooHigh(uint256 fee, uint256 maxFee);\n\n /// @notice Thrown when flash loan fee protocol share exceeds maximum allowed\n error FlashLoanProtocolShareTooHigh(uint256 fee, uint256 maxFee);\n\n // @notice Thrown when the vToken does not have enough cash to lend\n error InsufficientCash();\n\n /// @notice Thrown when the repayment amount is insufficient to cover the total fee\n error InsufficientRepayment(uint256 actualAmount, uint256 requiredTotalFee);\n\n /*** User Interface ***/\n\n function transfer(address dst, uint amount) external virtual returns (bool);\n\n function transferFrom(address src, address dst, uint amount) external virtual returns (bool);\n\n function approve(address spender, uint amount) external virtual returns (bool);\n\n function balanceOfUnderlying(address owner) external virtual returns (uint);\n\n function totalBorrowsCurrent() external virtual returns (uint);\n\n function borrowBalanceCurrent(address account) external virtual returns (uint);\n\n function seize(address liquidator, address borrower, uint seizeTokens) external virtual returns (uint);\n\n /*** Admin Function ***/\n function _setPendingAdmin(address payable newPendingAdmin) external virtual returns (uint);\n\n /*** Admin Function ***/\n function _acceptAdmin() external virtual returns (uint);\n\n /*** Admin Function ***/\n function _setReserveFactor(uint newReserveFactorMantissa) external virtual returns (uint);\n\n /*** Admin Function ***/\n function _reduceReserves(uint reduceAmount) external virtual returns (uint);\n\n function balanceOf(address owner) external view virtual returns (uint);\n\n function allowance(address owner, address spender) external view virtual returns (uint);\n\n function getAccountSnapshot(address account) external view virtual returns (uint, uint, uint, uint);\n\n function borrowRatePerBlock() external view virtual returns (uint);\n\n function supplyRatePerBlock() external view virtual returns (uint);\n\n function getCash() external view virtual returns (uint);\n\n function exchangeRateCurrent() public virtual returns (uint);\n\n function accrueInterest() public virtual returns (uint);\n\n /*** Admin Function ***/\n function _setComptroller(ComptrollerInterface newComptroller) public virtual returns (uint);\n\n /*** Admin Function ***/\n function _setInterestRateModel(InterestRateModelV8 newInterestRateModel) public virtual returns (uint);\n\n function borrowBalanceStored(address account) public view virtual returns (uint);\n\n function exchangeRateStored() public view virtual returns (uint);\n}\n\ninterface VBep20Interface {\n /*** User Interface ***/\n\n function mint(uint mintAmount) external returns (uint);\n\n function mintBehalf(address receiver, uint mintAmount) external returns (uint);\n\n function redeem(uint redeemTokens) external returns (uint);\n\n function redeemUnderlying(uint redeemAmount) external returns (uint);\n\n function borrow(uint borrowAmount) external returns (uint);\n\n function repayBorrow(uint repayAmount) external returns (uint);\n\n function repayBorrowBehalf(address borrower, uint repayAmount) external returns (uint);\n\n function liquidateBorrow(\n address borrower,\n uint repayAmount,\n VTokenInterface vTokenCollateral\n ) external returns (uint);\n\n /*** Admin Functions ***/\n\n function _addReserves(uint addAmount) external returns (uint);\n}\n\ninterface VDelegatorInterface {\n /**\n * @notice Emitted when implementation is changed\n */\n event NewImplementation(address oldImplementation, address newImplementation);\n\n /**\n * @notice Called by the admin to update the implementation of the delegator\n * @param implementation_ The address of the new implementation for delegation\n * @param allowResign Flag to indicate whether to call _resignImplementation on the old implementation\n * @param becomeImplementationData The encoded bytes data to be passed to _becomeImplementation\n */\n function _setImplementation(\n address implementation_,\n bool allowResign,\n bytes memory becomeImplementationData\n ) external;\n}\n\ninterface VDelegateInterface {\n /**\n * @notice Called by the delegator on a delegate to initialize it for duty\n * @dev Should revert if any issues arise which make it unfit for delegation\n * @param data The encoded bytes data for any initialization\n */\n function _becomeImplementation(bytes memory data) external;\n\n /**\n * @notice Called by the delegator on a delegate to forfeit its responsibility\n */\n function _resignImplementation() external;\n}\n" + }, + "contracts/Tokens/XVS/IXVS.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\n\npragma solidity 0.8.25;\n\ninterface IXVS {\n /// @notice BEP-20 token name for this token\n function name() external pure returns (string memory);\n\n /// @notice BEP-20 token symbol for this token\n function symbol() external pure returns (string memory);\n\n /// @notice BEP-20 token decimals for this token\n function decimals() external pure returns (uint8);\n\n /// @notice Total number of tokens in circulation\n function totalSupply() external pure returns (uint256);\n\n /// @notice A record of each accounts delegate\n function delegates(address) external view returns (address);\n\n /// @notice A checkpoint for marking number of votes from a given block\n struct Checkpoint {\n uint32 fromBlock;\n uint96 votes;\n }\n\n /// @notice A record of votes checkpoints for each account, by index\n function checkpoints(address, uint32) external view returns (Checkpoint memory);\n\n /// @notice The number of checkpoints for each account\n function numCheckpoints(address) external view returns (uint32);\n\n /// @notice The EIP-712 typehash for the contract's domain\n function DOMAIN_TYPEHASH() external pure returns (bytes32);\n\n /// @notice The EIP-712 typehash for the delegation struct used by the contract\n function DELEGATION_TYPEHASH() external pure returns (bytes32);\n\n /// @notice A record of states for signing / validating signatures\n function nonces(address) external view returns (uint256);\n\n /// @notice An event thats emitted when an account changes its delegate\n event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);\n\n /// @notice An event thats emitted when a delegate account's vote balance changes\n event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);\n\n /// @notice The standard BEP-20 transfer event\n event Transfer(address indexed from, address indexed to, uint256 amount);\n\n /// @notice The standard BEP-20 approval event\n event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n /**\n * @notice Get the number of tokens `spender` is approved to spend on behalf of `account`\n * @param account The address of the account holding the funds\n * @param spender The address of the account spending the funds\n * @return The number of tokens approved\n */\n function allowance(address account, address spender) external view returns (uint);\n\n /**\n * @notice Approve `spender` to transfer up to `amount` from `src`\n * @dev This will overwrite the approval amount for `spender`\n * @param spender The address of the account which may transfer tokens\n * @param rawAmount The number of tokens that are approved (2^256-1 means infinite)\n * @return Whether or not the approval succeeded\n */\n function approve(address spender, uint rawAmount) external returns (bool);\n\n /**\n * @notice Get the number of tokens held by the `account`\n * @param account The address of the account to get the balance of\n * @return The number of tokens held\n */\n function balanceOf(address account) external view returns (uint);\n\n /**\n * @notice Transfer `amount` tokens from `msg.sender` to `dst`\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transfer(address dst, uint rawAmount) external returns (bool);\n\n /**\n * @notice Transfer `amount` tokens from `src` to `dst`\n * @param src The address of the source account\n * @param dst The address of the destination account\n * @param rawAmount The number of tokens to transfer\n * @return Whether or not the transfer succeeded\n */\n function transferFrom(address src, address dst, uint rawAmount) external returns (bool);\n\n /**\n * @notice Delegate votes from `msg.sender` to `delegatee`\n * @param delegatee The address to delegate votes to\n */\n function delegate(address delegatee) external;\n\n /**\n * @notice Delegates votes from signatory to `delegatee`\n * @param delegatee The address to delegate votes to\n * @param nonce The contract state required to match the signature\n * @param expiry The time at which to expire the signature\n * @param v The recovery byte of the signature\n * @param r Half of the ECDSA signature pair\n * @param s Half of the ECDSA signature pair\n */\n function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) external;\n\n /**\n * @notice Gets the current votes balance for `account`\n * @param account The address to get votes balance\n * @return The number of current votes for `account`\n */\n function getCurrentVotes(address account) external view returns (uint96);\n\n /**\n * @notice Determine the prior number of votes for an account as of a block number\n * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n * @param account The address of the account to check\n * @param blockNumber The block number to get the vote balance at\n * @return The number of votes the account had as of the given block\n */\n function getPriorVotes(address account, uint blockNumber) external view returns (uint96);\n}\n" + }, + "contracts/Utils/CarefulMath.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Careful Math\n * @author Venus\n * @notice Derived from OpenZeppelin's SafeMath library\n * https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol\n */\ncontract CarefulMath {\n /**\n * @dev Possible error codes that we can return\n */\n enum MathError {\n NO_ERROR,\n DIVISION_BY_ZERO,\n INTEGER_OVERFLOW,\n INTEGER_UNDERFLOW\n }\n\n /**\n * @dev Multiplies two numbers, returns an error on overflow.\n */\n function mulUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (a == 0) {\n return (MathError.NO_ERROR, 0);\n }\n\n uint c;\n unchecked {\n c = a * b;\n }\n\n if (c / a != b) {\n return (MathError.INTEGER_OVERFLOW, 0);\n } else {\n return (MathError.NO_ERROR, c);\n }\n }\n\n /**\n * @dev Integer division of two numbers, truncating the quotient.\n */\n function divUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (b == 0) {\n return (MathError.DIVISION_BY_ZERO, 0);\n }\n\n return (MathError.NO_ERROR, a / b);\n }\n\n /**\n * @dev Subtracts two numbers, returns an error on overflow (i.e. if subtrahend is greater than minuend).\n */\n function subUInt(uint a, uint b) internal pure returns (MathError, uint) {\n if (b <= a) {\n unchecked {\n return (MathError.NO_ERROR, a - b);\n }\n } else {\n return (MathError.INTEGER_UNDERFLOW, 0);\n }\n }\n\n /**\n * @dev Adds two numbers, returns an error on overflow.\n */\n function addUInt(uint a, uint b) internal pure returns (MathError, uint) {\n uint c;\n unchecked {\n c = a + b;\n }\n\n if (c >= a) {\n return (MathError.NO_ERROR, c);\n } else {\n return (MathError.INTEGER_OVERFLOW, 0);\n }\n }\n\n /**\n * @dev add a and b and then subtract c\n */\n function addThenSubUInt(uint a, uint b, uint c) internal pure returns (MathError, uint) {\n (MathError err0, uint sum) = addUInt(a, b);\n\n if (err0 != MathError.NO_ERROR) {\n return (err0, 0);\n }\n\n return subUInt(sum, c);\n }\n}\n" + }, + "contracts/Utils/CheckpointView.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { ensureNonzeroAddress } from \"@venusprotocol/solidity-utilities/contracts/validators.sol\";\nimport { Address } from \"@openzeppelin/contracts/utils/Address.sol\";\n\n/**\n * @title Venus CheckpointView Contract\n * @notice A contract that calls a view function from two different contracts\n * based on whether a checkpoint in time has passed. Using this contract, we\n * can change dependencies at a certain timestamp, which is useful for\n * scheduled changes in, e.g., interest rate models.\n * @author Venus\n */\ncontract CheckpointView {\n using Address for address;\n\n address public immutable DATA_SOURCE_1;\n address public immutable DATA_SOURCE_2;\n uint256 public immutable CHECKPOINT_TIMESTAMP;\n\n /**\n * @notice Constructor\n * @param dataSource1 Data source to use before the checkpoint\n * @param dataSource2 Data source to use after the checkpoint\n * @param checkpointTimestamp Checkpoint timestamp\n */\n constructor(address dataSource1, address dataSource2, uint256 checkpointTimestamp) {\n ensureNonzeroAddress(address(dataSource1));\n ensureNonzeroAddress(address(dataSource2));\n DATA_SOURCE_1 = dataSource1;\n DATA_SOURCE_2 = dataSource2;\n CHECKPOINT_TIMESTAMP = checkpointTimestamp;\n }\n\n /**\n * @notice Fallback function that proxies the view calls to the current data source\n * @param input Input data (with a function selector) for the call\n * @return The data returned by the called function on the current data source\n */\n fallback(bytes calldata input) external returns (bytes memory) {\n return _getCurrentDataSource().functionStaticCall(input);\n }\n\n /**\n * @notice Returns the current data source contract (either the old one or the new one)\n * @return Data source contract in use\n */\n function currentDataSource() external view returns (address) {\n return _getCurrentDataSource();\n }\n\n /**\n * @dev Returns the current data source contract (either the old one or the new one)\n * @return Data source contract in use\n */\n function _getCurrentDataSource() internal view returns (address) {\n return (block.timestamp < CHECKPOINT_TIMESTAMP) ? DATA_SOURCE_1 : DATA_SOURCE_2;\n }\n}\n" + }, + "contracts/Utils/ErrorReporter.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { WeightFunction } from \"../Comptroller/Diamond/interfaces/IFacetBase.sol\";\n\ncontract ComptrollerErrorReporter {\n /// @notice Thrown when You are already in the selected pool.\n error AlreadyInSelectedPool();\n\n /// @notice Thrown when One or more of your assets are not compatible with the selected pool.\n error IncompatibleBorrowedAssets();\n\n /// @notice Thrown when Switching to this pool would fail the liquidity check or lead to liquidation.\n error LiquidityCheckFailed(uint256 errorCode, uint256 shortfall);\n\n /// @notice Thrown when trying to call pool-specific methods on the Core Pool\n error InvalidOperationForCorePool();\n\n /// @notice Thrown when input array lengths do not match\n error ArrayLengthMismatch();\n\n /// @notice Thrown when market trying to add in a pool is not listed in the core pool\n error MarketNotListedInCorePool();\n\n /// @notice Thrown when market is not set in the _poolMarkets mapping\n error MarketConfigNotFound();\n\n /// @notice Thrown when borrowing is not allowed in the selected pool for a given market.\n error BorrowNotAllowedInPool();\n\n /// @notice Thrown when trying to remove a market that is not listed in the given pool.\n error PoolMarketNotFound(uint96 poolId, address vToken);\n\n /// @notice Thrown when a given pool ID does not exist\n error PoolDoesNotExist(uint96 poolId);\n\n /// @notice Thrown when the pool label is empty\n error EmptyPoolLabel();\n\n /// @notice Thrown when a vToken is already listed in the specified pool\n error MarketAlreadyListed(uint96 poolId, address vToken);\n\n /// @notice Thrown when an invalid weighting strategy is provided\n error InvalidWeightingStrategy(WeightFunction strategy);\n\n // @notice Thrown when no assets are requested for flash loan\n error NoAssetsRequested();\n\n // @notice Thrown when invalid flash loan parameters are provided\n error InvalidFlashLoanParams();\n\n // @notice Thrown when flash loan is not enabled on the vToken\n error FlashLoanNotEnabled();\n\n // @notice Thrown when the sender is not authorized to use flashloan onBehalfOf\n error SenderNotAuthorizedForFlashLoan(address sender);\n\n // @notice Thrown when the onBehalfOf didn't approve the contract that receives flashloan\n error NotAnApprovedDelegate();\n\n // @notice Thrown when executeOperation on the receiver contract fails\n error ExecuteFlashLoanFailed();\n\n // @notice Thrown when the requested amount is zero\n error InvalidAmount();\n\n // @notice Thrown when failing to create a debt position in mode 1\n error FailedToCreateDebtPosition();\n\n /// @notice Thrown when attempting to interact with an inactive pool\n error InactivePool(uint96 poolId);\n\n /// @notice Thrown when repayment amount is insufficient to cover the fee\n error NotEnoughRepayment(uint256 repaid, uint256 required);\n\n /// @notice Thrown when the vToken market is not listed\n error MarketNotListed(address vToken);\n\n /// @notice Thrown when flash loans are paused system-wide\n error FlashLoanPausedSystemWide();\n\n /// @notice Thrown when too many assets are requested in a single flash loan\n error TooManyAssetsRequested(uint256 requested, uint256 maximum);\n\n enum Error {\n NO_ERROR,\n UNAUTHORIZED,\n COMPTROLLER_MISMATCH,\n INSUFFICIENT_SHORTFALL,\n INSUFFICIENT_LIQUIDITY,\n INVALID_CLOSE_FACTOR,\n INVALID_COLLATERAL_FACTOR,\n INVALID_LIQUIDATION_INCENTIVE,\n MARKET_NOT_ENTERED, // no longer possible\n MARKET_NOT_LISTED,\n MARKET_ALREADY_LISTED,\n MATH_ERROR,\n NONZERO_BORROW_BALANCE,\n PRICE_ERROR,\n REJECTION,\n SNAPSHOT_ERROR,\n TOO_MANY_ASSETS,\n TOO_MUCH_REPAY,\n INSUFFICIENT_BALANCE_FOR_VAI,\n MARKET_NOT_COLLATERAL,\n INVALID_LIQUIDATION_THRESHOLD\n }\n\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n EXIT_MARKET_BALANCE_OWED,\n EXIT_MARKET_REJECTION,\n SET_CLOSE_FACTOR_OWNER_CHECK,\n SET_CLOSE_FACTOR_VALIDATION,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_NO_EXISTS,\n SET_COLLATERAL_FACTOR_VALIDATION,\n SET_COLLATERAL_FACTOR_WITHOUT_PRICE,\n SET_IMPLEMENTATION_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_OWNER_CHECK,\n SET_LIQUIDATION_INCENTIVE_VALIDATION,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\n SET_PRICE_ORACLE_OWNER_CHECK,\n SUPPORT_MARKET_EXISTS,\n SUPPORT_MARKET_OWNER_CHECK,\n SET_PAUSE_GUARDIAN_OWNER_CHECK,\n SET_VAI_MINT_RATE_CHECK,\n SET_VAICONTROLLER_OWNER_CHECK,\n SET_MINTED_VAI_REJECTION,\n SET_TREASURY_OWNER_CHECK,\n UNLIST_MARKET_NOT_LISTED,\n SET_LIQUIDATION_THRESHOLD_VALIDATION,\n COLLATERAL_FACTOR_GREATER_THAN_LIQUIDATION_THRESHOLD\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n\ncontract TokenErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED,\n BAD_INPUT,\n COMPTROLLER_REJECTION,\n COMPTROLLER_CALCULATION_ERROR,\n INTEREST_RATE_MODEL_ERROR,\n INVALID_ACCOUNT_PAIR,\n INVALID_CLOSE_AMOUNT_REQUESTED,\n INVALID_COLLATERAL_FACTOR,\n MATH_ERROR,\n MARKET_NOT_FRESH,\n MARKET_NOT_LISTED,\n TOKEN_INSUFFICIENT_ALLOWANCE,\n TOKEN_INSUFFICIENT_BALANCE,\n TOKEN_INSUFFICIENT_CASH,\n TOKEN_TRANSFER_IN_FAILED,\n TOKEN_TRANSFER_OUT_FAILED,\n TOKEN_PRICE_ERROR\n }\n\n /*\n * Note: FailureInfo (but not Error) is kept in alphabetical order\n * This is because FailureInfo grows significantly faster, and\n * the order of Error has some meaning, while the order of FailureInfo\n * is entirely arbitrary.\n */\n enum FailureInfo {\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCRUE_INTEREST_ACCUMULATED_INTEREST_CALCULATION_FAILED,\n ACCRUE_INTEREST_BORROW_RATE_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_BORROW_INDEX_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_BORROWS_CALCULATION_FAILED,\n ACCRUE_INTEREST_NEW_TOTAL_RESERVES_CALCULATION_FAILED,\n ACCRUE_INTEREST_SIMPLE_INTEREST_FACTOR_CALCULATION_FAILED,\n BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n BORROW_ACCRUE_INTEREST_FAILED,\n BORROW_CASH_NOT_AVAILABLE,\n BORROW_FRESHNESS_CHECK,\n BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n BORROW_MARKET_NOT_LISTED,\n BORROW_COMPTROLLER_REJECTION,\n LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\n LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\n LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n LIQUIDATE_COMPTROLLER_REJECTION,\n LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\n LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\n LIQUIDATE_FRESHNESS_CHECK,\n LIQUIDATE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\n LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\n LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\n LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\n LIQUIDATE_SEIZE_TOO_MUCH,\n MINT_ACCRUE_INTEREST_FAILED,\n MINT_COMPTROLLER_REJECTION,\n MINT_EXCHANGE_CALCULATION_FAILED,\n MINT_EXCHANGE_RATE_READ_FAILED,\n MINT_FRESHNESS_CHECK,\n MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n MINT_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n MINT_TRANSFER_IN_FAILED,\n MINT_TRANSFER_IN_NOT_POSSIBLE,\n REDEEM_ACCRUE_INTEREST_FAILED,\n REDEEM_COMPTROLLER_REJECTION,\n REDEEM_EXCHANGE_TOKENS_CALCULATION_FAILED,\n REDEEM_EXCHANGE_AMOUNT_CALCULATION_FAILED,\n REDEEM_EXCHANGE_RATE_READ_FAILED,\n REDEEM_FRESHNESS_CHECK,\n REDEEM_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED,\n REDEEM_NEW_TOTAL_SUPPLY_CALCULATION_FAILED,\n REDEEM_TRANSFER_OUT_NOT_POSSIBLE,\n REDUCE_RESERVES_ACCRUE_INTEREST_FAILED,\n REDUCE_RESERVES_ADMIN_CHECK,\n REDUCE_RESERVES_CASH_NOT_AVAILABLE,\n REDUCE_RESERVES_FRESH_CHECK,\n REDUCE_RESERVES_VALIDATION,\n REPAY_BEHALF_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCRUE_INTEREST_FAILED,\n REPAY_BORROW_ACCUMULATED_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_COMPTROLLER_REJECTION,\n REPAY_BORROW_FRESHNESS_CHECK,\n REPAY_BORROW_NEW_ACCOUNT_BORROW_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_NEW_TOTAL_BALANCE_CALCULATION_FAILED,\n REPAY_BORROW_TRANSFER_IN_NOT_POSSIBLE,\n SET_COLLATERAL_FACTOR_OWNER_CHECK,\n SET_COLLATERAL_FACTOR_VALIDATION,\n SET_COMPTROLLER_OWNER_CHECK,\n SET_INTEREST_RATE_MODEL_ACCRUE_INTEREST_FAILED,\n SET_INTEREST_RATE_MODEL_FRESH_CHECK,\n SET_INTEREST_RATE_MODEL_OWNER_CHECK,\n SET_MAX_ASSETS_OWNER_CHECK,\n SET_ORACLE_MARKET_NOT_LISTED,\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_RESERVE_FACTOR_ACCRUE_INTEREST_FAILED,\n SET_RESERVE_FACTOR_ADMIN_CHECK,\n SET_RESERVE_FACTOR_FRESH_CHECK,\n SET_RESERVE_FACTOR_BOUNDS_CHECK,\n TRANSFER_COMPTROLLER_REJECTION,\n TRANSFER_NOT_ALLOWED,\n TRANSFER_NOT_ENOUGH,\n TRANSFER_TOO_MUCH,\n ADD_RESERVES_ACCRUE_INTEREST_FAILED,\n ADD_RESERVES_FRESH_CHECK,\n ADD_RESERVES_TRANSFER_IN_NOT_POSSIBLE,\n TOKEN_GET_UNDERLYING_PRICE_ERROR,\n REPAY_VAI_COMPTROLLER_REJECTION,\n REPAY_VAI_FRESHNESS_CHECK,\n VAI_MINT_EXCHANGE_CALCULATION_FAILED,\n SFT_MINT_NEW_ACCOUNT_BALANCE_CALCULATION_FAILED\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n\ncontract VAIControllerErrorReporter {\n enum Error {\n NO_ERROR,\n UNAUTHORIZED, // The sender is not authorized to perform this action.\n REJECTION, // The action would violate the comptroller, vaicontroller policy.\n SNAPSHOT_ERROR, // The comptroller could not get the account borrows and exchange rate from the market.\n PRICE_ERROR, // The comptroller could not obtain a required price of an asset.\n MATH_ERROR, // A math calculation error occurred.\n INSUFFICIENT_BALANCE_FOR_VAI // Caller does not have sufficient balance to mint VAI.\n }\n\n enum FailureInfo {\n SET_PENDING_ADMIN_OWNER_CHECK,\n SET_PENDING_IMPLEMENTATION_OWNER_CHECK,\n SET_COMPTROLLER_OWNER_CHECK,\n ACCEPT_ADMIN_PENDING_ADMIN_CHECK,\n ACCEPT_PENDING_IMPLEMENTATION_ADDRESS_CHECK,\n VAI_MINT_REJECTION,\n VAI_BURN_REJECTION,\n VAI_LIQUIDATE_ACCRUE_BORROW_INTEREST_FAILED,\n VAI_LIQUIDATE_ACCRUE_COLLATERAL_INTEREST_FAILED,\n VAI_LIQUIDATE_COLLATERAL_FRESHNESS_CHECK,\n VAI_LIQUIDATE_COMPTROLLER_REJECTION,\n VAI_LIQUIDATE_COMPTROLLER_CALCULATE_AMOUNT_SEIZE_FAILED,\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_UINT_MAX,\n VAI_LIQUIDATE_CLOSE_AMOUNT_IS_ZERO,\n VAI_LIQUIDATE_FRESHNESS_CHECK,\n VAI_LIQUIDATE_LIQUIDATOR_IS_BORROWER,\n VAI_LIQUIDATE_REPAY_BORROW_FRESH_FAILED,\n VAI_LIQUIDATE_SEIZE_BALANCE_INCREMENT_FAILED,\n VAI_LIQUIDATE_SEIZE_BALANCE_DECREMENT_FAILED,\n VAI_LIQUIDATE_SEIZE_COMPTROLLER_REJECTION,\n VAI_LIQUIDATE_SEIZE_LIQUIDATOR_IS_BORROWER,\n VAI_LIQUIDATE_SEIZE_TOO_MUCH,\n MINT_FEE_CALCULATION_FAILED,\n SET_TREASURY_OWNER_CHECK\n }\n\n /**\n * @dev `error` corresponds to enum Error; `info` corresponds to enum FailureInfo, and `detail` is an arbitrary\n * contract-specific code that enables us to report opaque error codes from upgradeable contracts.\n **/\n event Failure(uint error, uint info, uint detail);\n\n /**\n * @dev use this when reporting a known error from the money market or a non-upgradeable collaborator\n */\n function fail(Error err, FailureInfo info) internal returns (uint) {\n emit Failure(uint(err), uint(info), 0);\n\n return uint(err);\n }\n\n /**\n * @dev use this when reporting an opaque error from an upgradeable collaborator contract\n */\n function failOpaque(Error err, FailureInfo info, uint opaqueError) internal returns (uint) {\n emit Failure(uint(err), uint(info), opaqueError);\n\n return uint(err);\n }\n}\n" + }, + "contracts/Utils/Exponential.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\nimport { CarefulMath } from \"./CarefulMath.sol\";\nimport { ExponentialNoError } from \"./ExponentialNoError.sol\";\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Venus\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract Exponential is CarefulMath, ExponentialNoError {\n /**\n * @dev Creates an exponential from numerator and denominator values.\n * Note: Returns an error if (`num` * 10e18) > MAX_INT,\n * or if `denom` is zero.\n */\n function getExp(uint num, uint denom) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint scaledNumerator) = mulUInt(num, expScale);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n (MathError err1, uint rational) = divUInt(scaledNumerator, denom);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: rational }));\n }\n\n /**\n * @dev Adds two exponentials, returning a new exponential.\n */\n function addExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError error, uint result) = addUInt(a.mantissa, b.mantissa);\n\n return (error, Exp({ mantissa: result }));\n }\n\n /**\n * @dev Subtracts two exponentials, returning a new exponential.\n */\n function subExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError error, uint result) = subUInt(a.mantissa, b.mantissa);\n\n return (error, Exp({ mantissa: result }));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, returning a new Exp.\n */\n function mulScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint scaledMantissa) = mulUInt(a.mantissa, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: scaledMantissa }));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mulScalarTruncate(Exp memory a, uint scalar) internal pure returns (MathError, uint) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return (MathError.NO_ERROR, truncate(product));\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n function mulScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (MathError, uint) {\n (MathError err, Exp memory product) = mulScalar(a, scalar);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return addUInt(truncate(product), addend);\n }\n\n /**\n * @dev Divide an Exp by a scalar, returning a new Exp.\n */\n function divScalar(Exp memory a, uint scalar) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint descaledMantissa) = divUInt(a.mantissa, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n return (MathError.NO_ERROR, Exp({ mantissa: descaledMantissa }));\n }\n\n /**\n * @dev Divide a scalar by an Exp, returning a new Exp.\n */\n function divScalarByExp(uint scalar, Exp memory divisor) internal pure returns (MathError, Exp memory) {\n /*\n We are doing this as:\n getExp(mulUInt(expScale, scalar), divisor.mantissa)\n\n How it works:\n Exp = a / b;\n Scalar = s;\n `s / (a / b)` = `b * s / a` and since for an Exp `a = mantissa, b = expScale`\n */\n (MathError err0, uint numerator) = mulUInt(expScale, scalar);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n return getExp(numerator, divisor.mantissa);\n }\n\n /**\n * @dev Divide a scalar by an Exp, then truncate to return an unsigned integer.\n */\n function divScalarByExpTruncate(uint scalar, Exp memory divisor) internal pure returns (MathError, uint) {\n (MathError err, Exp memory fraction) = divScalarByExp(scalar, divisor);\n if (err != MathError.NO_ERROR) {\n return (err, 0);\n }\n\n return (MathError.NO_ERROR, truncate(fraction));\n }\n\n /**\n * @dev Multiplies two exponentials, returning a new exponential.\n */\n function mulExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n (MathError err0, uint doubleScaledProduct) = mulUInt(a.mantissa, b.mantissa);\n if (err0 != MathError.NO_ERROR) {\n return (err0, Exp({ mantissa: 0 }));\n }\n\n // We add half the scale before dividing so that we get rounding instead of truncation.\n // See \"Listing 6\" and text above it at https://accu.org/index.php/journals/1717\n // Without this change, a result like 6.6...e-19 will be truncated to 0 instead of being rounded to 1e-18.\n (MathError err1, uint doubleScaledProductWithHalfScale) = addUInt(halfExpScale, doubleScaledProduct);\n if (err1 != MathError.NO_ERROR) {\n return (err1, Exp({ mantissa: 0 }));\n }\n\n (MathError err2, uint product) = divUInt(doubleScaledProductWithHalfScale, expScale);\n // The only error `div` can return is MathError.DIVISION_BY_ZERO but we control `expScale` and it is not zero.\n assert(err2 == MathError.NO_ERROR);\n\n return (MathError.NO_ERROR, Exp({ mantissa: product }));\n }\n\n /**\n * @dev Multiplies two exponentials given their mantissas, returning a new exponential.\n */\n function mulExp(uint a, uint b) internal pure returns (MathError, Exp memory) {\n return mulExp(Exp({ mantissa: a }), Exp({ mantissa: b }));\n }\n\n /**\n * @dev Multiplies three exponentials, returning a new exponential.\n */\n function mulExp3(Exp memory a, Exp memory b, Exp memory c) internal pure returns (MathError, Exp memory) {\n (MathError err, Exp memory ab) = mulExp(a, b);\n if (err != MathError.NO_ERROR) {\n return (err, ab);\n }\n return mulExp(ab, c);\n }\n\n /**\n * @dev Divides two exponentials, returning a new exponential.\n * (a/scale) / (b/scale) = (a/scale) * (scale/b) = a/b,\n * which we can scale as an Exp by calling getExp(a.mantissa, b.mantissa)\n */\n function divExp(Exp memory a, Exp memory b) internal pure returns (MathError, Exp memory) {\n return getExp(a.mantissa, b.mantissa);\n }\n}\n" + }, + "contracts/Utils/ExponentialNoError.sol": { + "content": "// SPDX-License-Identifier: BSD-3-Clause\npragma solidity 0.8.25;\n\n/**\n * @title Exponential module for storing fixed-precision decimals\n * @author Compound\n * @notice Exp is a struct which stores decimals with a fixed precision of 18 decimal places.\n * Thus, if we wanted to store the 5.1, mantissa would store 5.1e18. That is:\n * `Exp({mantissa: 5100000000000000000})`.\n */\ncontract ExponentialNoError {\n uint internal constant expScale = 1e18;\n uint internal constant doubleScale = 1e36;\n uint internal constant halfExpScale = expScale / 2;\n uint internal constant mantissaOne = expScale;\n\n struct Exp {\n uint mantissa;\n }\n\n struct Double {\n uint mantissa;\n }\n\n /**\n * @dev Truncates the given exp to a whole number value.\n * For example, truncate(Exp{mantissa: 15 * expScale}) = 15\n */\n function truncate(Exp memory exp) internal pure returns (uint) {\n // Note: We are not using careful math here as we're performing a division that cannot fail\n return exp.mantissa / expScale;\n }\n\n /**\n * @dev Multiply an Exp by a scalar, then truncate to return an unsigned integer.\n */\n function mul_ScalarTruncate(Exp memory a, uint scalar) internal pure returns (uint) {\n Exp memory product = mul_(a, scalar);\n return truncate(product);\n }\n\n /**\n * @dev Multiply an Exp by a scalar, truncate, then add an to an unsigned integer, returning an unsigned integer.\n */\n function mul_ScalarTruncateAddUInt(Exp memory a, uint scalar, uint addend) internal pure returns (uint) {\n Exp memory product = mul_(a, scalar);\n return add_(truncate(product), addend);\n }\n\n /**\n * @dev Checks if first Exp is less than second Exp.\n */\n function lessThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa < right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp <= right Exp.\n */\n function lessThanOrEqualExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa <= right.mantissa;\n }\n\n /**\n * @dev Checks if left Exp > right Exp.\n */\n function greaterThanExp(Exp memory left, Exp memory right) internal pure returns (bool) {\n return left.mantissa > right.mantissa;\n }\n\n /**\n * @dev returns true if Exp is exactly zero\n */\n function isZeroExp(Exp memory value) internal pure returns (bool) {\n return value.mantissa == 0;\n }\n\n function safe224(uint n, string memory errorMessage) internal pure returns (uint224) {\n require(n < 2 ** 224, errorMessage);\n return uint224(n);\n }\n\n function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {\n require(n < 2 ** 32, errorMessage);\n return uint32(n);\n }\n\n function add_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: add_(a.mantissa, b.mantissa) });\n }\n\n function add_(uint a, uint b) internal pure returns (uint) {\n return add_(a, b, \"addition overflow\");\n }\n\n function add_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n uint c = a + b;\n require(c >= a, errorMessage);\n return c;\n }\n\n function sub_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: sub_(a.mantissa, b.mantissa) });\n }\n\n function sub_(uint a, uint b) internal pure returns (uint) {\n return sub_(a, b, \"subtraction underflow\");\n }\n\n function sub_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b <= a, errorMessage);\n return a - b;\n }\n\n function mul_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b.mantissa) / expScale });\n }\n\n function mul_(Exp memory a, uint b) internal pure returns (Exp memory) {\n return Exp({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint a, Exp memory b) internal pure returns (uint) {\n return mul_(a, b.mantissa) / expScale;\n }\n\n function mul_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b.mantissa) / doubleScale });\n }\n\n function mul_(Double memory a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: mul_(a.mantissa, b) });\n }\n\n function mul_(uint a, Double memory b) internal pure returns (uint) {\n return mul_(a, b.mantissa) / doubleScale;\n }\n\n function mul_(uint a, uint b) internal pure returns (uint) {\n return mul_(a, b, \"multiplication overflow\");\n }\n\n function mul_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n if (a == 0 || b == 0) {\n return 0;\n }\n uint c = a * b;\n require(c / a == b, errorMessage);\n return c;\n }\n\n function div_(Exp memory a, Exp memory b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(mul_(a.mantissa, expScale), b.mantissa) });\n }\n\n function div_(Exp memory a, uint b) internal pure returns (Exp memory) {\n return Exp({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint a, Exp memory b) internal pure returns (uint) {\n return div_(mul_(a, expScale), b.mantissa);\n }\n\n function div_(Double memory a, Double memory b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a.mantissa, doubleScale), b.mantissa) });\n }\n\n function div_(Double memory a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(a.mantissa, b) });\n }\n\n function div_(uint a, Double memory b) internal pure returns (uint) {\n return div_(mul_(a, doubleScale), b.mantissa);\n }\n\n function div_(uint a, uint b) internal pure returns (uint) {\n return div_(a, b, \"divide by zero\");\n }\n\n function div_(uint a, uint b, string memory errorMessage) internal pure returns (uint) {\n require(b > 0, errorMessage);\n return a / b;\n }\n\n function fraction(uint a, uint b) internal pure returns (Double memory) {\n return Double({ mantissa: div_(mul_(a, doubleScale), b) });\n }\n}\n" + }, + "contracts/Utils/ReentrancyGuardTransient.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuardTransient.sol)\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/ReentrancyGuardTransient.sol\npragma solidity ^0.8.25;\n\nimport { TransientSlot } from \"./TransientSlot.sol\";\n\n/**\n * @dev Variant of {ReentrancyGuard} that uses transient storage.\n *\n * NOTE: This variant only works on networks where EIP-1153 is available.\n *\n * _Available since v5.1._\n */\nabstract contract ReentrancyGuardTransient {\n using TransientSlot for *;\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ReentrancyGuard\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant REENTRANCY_GUARD_STORAGE =\n 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;\n\n /**\n * @dev Unauthorized reentrant call.\n */\n error ReentrancyGuardReentrantCall();\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n /**\n * @dev Returns true if the reentrancy guard is currently set to \"entered\", which indicates there is a\n * `nonReentrant` function in the call stack.\n */\n function _reentrancyGuardEntered() internal view returns (bool) {\n return REENTRANCY_GUARD_STORAGE.asBoolean().tload();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be NOT_ENTERED\n if (_reentrancyGuardEntered()) {\n revert ReentrancyGuardReentrantCall();\n }\n\n // Any calls to nonReentrant after this point will fail\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);\n }\n\n function _nonReentrantAfter() private {\n REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);\n }\n}\n" + }, + "contracts/Utils/TransientSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/TransientSlot.sol)\n// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.\n// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/TransientSlot.sol\npragma solidity ^0.8.25;\n\n/**\n * @dev Library for reading and writing value-types to specific transient storage slots.\n *\n * Transient slots are often used to store temporary values that are removed after the current transaction.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * * Example reading and writing values using transient storage:\n * ```solidity\n * contract Lock {\n * using TransientSlot for *;\n *\n * // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.\n * bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;\n *\n * modifier locked() {\n * require(!_LOCK_SLOT.asBoolean().tload());\n *\n * _LOCK_SLOT.asBoolean().tstore(true);\n * _;\n * _LOCK_SLOT.asBoolean().tstore(false);\n * }\n * }\n * ```\n *\n * TIP: Consider using this library along with {SlotDerivation}.\n */\nlibrary TransientSlot {\n /**\n * @dev UDVT that represent a slot holding a address.\n */\n type AddressSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a AddressSlot.\n */\n function asAddress(bytes32 slot) internal pure returns (AddressSlot) {\n return AddressSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a bool.\n */\n type BooleanSlot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a BooleanSlot.\n */\n function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {\n return BooleanSlot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a bytes32.\n */\n type Bytes32Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Bytes32Slot.\n */\n function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {\n return Bytes32Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a uint256.\n */\n type Uint256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Uint256Slot.\n */\n function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {\n return Uint256Slot.wrap(slot);\n }\n\n /**\n * @dev UDVT that represent a slot holding a int256.\n */\n type Int256Slot is bytes32;\n\n /**\n * @dev Cast an arbitrary slot to a Int256Slot.\n */\n function asInt256(bytes32 slot) internal pure returns (Int256Slot) {\n return Int256Slot.wrap(slot);\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(AddressSlot slot) internal view returns (address value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(AddressSlot slot, address value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(BooleanSlot slot) internal view returns (bool value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(BooleanSlot slot, bool value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Bytes32Slot slot) internal view returns (bytes32 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Bytes32Slot slot, bytes32 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Uint256Slot slot) internal view returns (uint256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Uint256Slot slot, uint256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n\n /**\n * @dev Load the value held at location `slot` in transient storage.\n */\n function tload(Int256Slot slot) internal view returns (int256 value) {\n assembly (\"memory-safe\") {\n value := tload(slot)\n }\n }\n\n /**\n * @dev Store `value` at location `slot` in transient storage.\n */\n function tstore(Int256Slot slot, int256 value) internal {\n assembly (\"memory-safe\") {\n tstore(slot, value)\n }\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor (address initialOwner) {\n _transferOwnership(initialOwner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/interfaces/draft-IERC1822.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/beacon/IBeacon.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/ERC1967/ERC1967Proxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Proxy.sol\";\nimport \"./ERC1967Upgrade.sol\";\n\n/**\n * @dev This contract implements an upgradeable proxy. It is upgradeable because calls are delegated to an\n * implementation address that can be changed. This address is stored in storage in the location specified by\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967], so that it doesn't conflict with the storage layout of the\n * implementation behind the proxy.\n */\ncontract ERC1967Proxy is Proxy, ERC1967Upgrade {\n /**\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `_logic`.\n *\n * If `_data` is nonempty, it's used as data in a delegate call to `_logic`. This will typically be an encoded\n * function call, and allows initializating the storage of the proxy like a Solidity constructor.\n */\n constructor(address _logic, bytes memory _data) payable {\n assert(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.implementation\")) - 1));\n _upgradeToAndCall(_logic, _data, false);\n }\n\n /**\n * @dev Returns the current implementation address.\n */\n function _implementation() internal view virtual override returns (address impl) {\n return ERC1967Upgrade._getImplementation();\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/ERC1967/ERC1967Upgrade.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view virtual returns (address) {\n return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(Address.isContract(IBeacon(newBeacon).implementation()), \"ERC1967: beacon implementation is not a contract\");\n StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n }\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/Proxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (proxy/Proxy.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM\n * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to\n * be specified by overriding the virtual {_implementation} function.\n *\n * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a\n * different contract through the {_delegate} function.\n *\n * The success and return data of the delegated call will be returned back to the caller of the proxy.\n */\nabstract contract Proxy {\n /**\n * @dev Delegates the current call to `implementation`.\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual {\n assembly {\n // Copy msg.data. We take full control of memory in this inline assembly\n // block because it will not return to Solidity code. We overwrite the\n // Solidity scratch pad at memory position 0.\n calldatacopy(0, 0, calldatasize())\n\n // Call the implementation.\n // out and outsize are 0 because we don't know the size yet.\n let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)\n\n // Copy the returned data.\n returndatacopy(0, 0, returndatasize())\n\n switch result\n // delegatecall returns 0 on error.\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n /**\n * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function\n * and {_fallback} should delegate.\n */\n function _implementation() internal view virtual returns (address);\n\n /**\n * @dev Delegates the current call to the address returned by `_implementation()`.\n *\n * This function does not return to its internall call site, it will return directly to the external caller.\n */\n function _fallback() internal virtual {\n _beforeFallback();\n _delegate(_implementation());\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other\n * function in the contract matches the call data.\n */\n fallback() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data\n * is empty.\n */\n receive() external payable virtual {\n _fallback();\n }\n\n /**\n * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`\n * call, or as part of the Solidity `fallback` or `receive` functions.\n *\n * If overriden should call `super._beforeFallback()`.\n */\n function _beforeFallback() internal virtual {}\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/ProxyAdmin.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./TransparentUpgradeableProxy.sol\";\nimport \"../../access/Ownable.sol\";\n\n/**\n * @dev This is an auxiliary contract meant to be assigned as the admin of a {TransparentUpgradeableProxy}. For an\n * explanation of why you would want to use this see the documentation for {TransparentUpgradeableProxy}.\n */\ncontract ProxyAdmin is Ownable {\n\n constructor (address initialOwner) Ownable(initialOwner) {}\n\n /**\n * @dev Returns the current implementation of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyImplementation(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"implementation()\")) == 0x5c60da1b\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"5c60da1b\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Returns the current admin of `proxy`.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function getProxyAdmin(TransparentUpgradeableProxy proxy) public view virtual returns (address) {\n // We need to manually run the static call since the getter cannot be flagged as view\n // bytes4(keccak256(\"admin()\")) == 0xf851a440\n (bool success, bytes memory returndata) = address(proxy).staticcall(hex\"f851a440\");\n require(success);\n return abi.decode(returndata, (address));\n }\n\n /**\n * @dev Changes the admin of `proxy` to `newAdmin`.\n *\n * Requirements:\n *\n * - This contract must be the current admin of `proxy`.\n */\n function changeProxyAdmin(TransparentUpgradeableProxy proxy, address newAdmin) public virtual onlyOwner {\n proxy.changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation`. See {TransparentUpgradeableProxy-upgradeTo}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgrade(TransparentUpgradeableProxy proxy, address implementation) public virtual onlyOwner {\n proxy.upgradeTo(implementation);\n }\n\n /**\n * @dev Upgrades `proxy` to `implementation` and calls a function on the new implementation. See\n * {TransparentUpgradeableProxy-upgradeToAndCall}.\n *\n * Requirements:\n *\n * - This contract must be the admin of `proxy`.\n */\n function upgradeAndCall(\n TransparentUpgradeableProxy proxy,\n address implementation,\n bytes memory data\n ) public payable virtual onlyOwner {\n proxy.upgradeToAndCall{value: msg.value}(implementation, data);\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/proxy/transparent/TransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract TransparentUpgradeableProxy is ERC1967Proxy {\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _changeAdmin(admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-changeProxyAdmin}.\n */\n function changeAdmin(address newAdmin) external virtual ifAdmin {\n _changeAdmin(newAdmin);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0-rc.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/openzeppelin/utils/StorageSlot.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/proxy/OptimizedTransparentUpgradeableProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/transparent/TransparentUpgradeableProxy.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../openzeppelin/proxy/ERC1967/ERC1967Proxy.sol\";\n\n/**\n * @dev This contract implements a proxy that is upgradeable by an admin.\n *\n * To avoid https://medium.com/nomic-labs-blog/malicious-backdoors-in-ethereum-proxies-62629adf3357[proxy selector\n * clashing], which can potentially be used in an attack, this contract uses the\n * https://blog.openzeppelin.com/the-transparent-proxy-pattern/[transparent proxy pattern]. This pattern implies two\n * things that go hand in hand:\n *\n * 1. If any account other than the admin calls the proxy, the call will be forwarded to the implementation, even if\n * that call matches one of the admin functions exposed by the proxy itself.\n * 2. If the admin calls the proxy, it can access the admin functions, but its calls will never be forwarded to the\n * implementation. If the admin tries to call a function on the implementation it will fail with an error that says\n * \"admin cannot fallback to proxy target\".\n *\n * These properties mean that the admin account can only be used for admin actions like upgrading the proxy or changing\n * the admin, so it's best if it's a dedicated account that is not used for anything else. This will avoid headaches due\n * to sudden errors when trying to call a function from the proxy implementation.\n *\n * Our recommendation is for the dedicated account to be an instance of the {ProxyAdmin} contract. If set up this way,\n * you should think of the `ProxyAdmin` instance as the real administrative interface of your proxy.\n */\ncontract OptimizedTransparentUpgradeableProxy is ERC1967Proxy {\n address internal immutable _ADMIN;\n\n /**\n * @dev Initializes an upgradeable proxy managed by `_admin`, backed by the implementation at `_logic`, and\n * optionally initialized with `_data` as explained in {ERC1967Proxy-constructor}.\n */\n constructor(\n address _logic,\n address admin_,\n bytes memory _data\n ) payable ERC1967Proxy(_logic, _data) {\n assert(_ADMIN_SLOT == bytes32(uint256(keccak256(\"eip1967.proxy.admin\")) - 1));\n _ADMIN = admin_;\n\n // still store it to work with EIP-1967\n bytes32 slot = _ADMIN_SLOT;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n sstore(slot, admin_)\n }\n emit AdminChanged(address(0), admin_);\n }\n\n /**\n * @dev Modifier used internally that will delegate the call to the implementation unless the sender is the admin.\n */\n modifier ifAdmin() {\n if (msg.sender == _getAdmin()) {\n _;\n } else {\n _fallback();\n }\n }\n\n /**\n * @dev Returns the current admin.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyAdmin}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`\n */\n function admin() external ifAdmin returns (address admin_) {\n admin_ = _getAdmin();\n }\n\n /**\n * @dev Returns the current implementation.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-getProxyImplementation}.\n *\n * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using the\n * https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.\n * `0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc`\n */\n function implementation() external ifAdmin returns (address implementation_) {\n implementation_ = _implementation();\n }\n\n /**\n * @dev Upgrade the implementation of the proxy.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgrade}.\n */\n function upgradeTo(address newImplementation) external ifAdmin {\n _upgradeToAndCall(newImplementation, bytes(\"\"), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy, and then call a function from the new implementation as specified\n * by `data`, which should be an encoded function call. This is useful to initialize new storage variables in the\n * proxied contract.\n *\n * NOTE: Only the admin can call this function. See {ProxyAdmin-upgradeAndCall}.\n */\n function upgradeToAndCall(address newImplementation, bytes calldata data) external payable ifAdmin {\n _upgradeToAndCall(newImplementation, data, true);\n }\n\n /**\n * @dev Returns the current admin.\n */\n function _admin() internal view virtual returns (address) {\n return _getAdmin();\n }\n\n /**\n * @dev Makes sure the admin cannot access the fallback function. See {Proxy-_beforeFallback}.\n */\n function _beforeFallback() internal virtual override {\n require(msg.sender != _getAdmin(), \"TransparentUpgradeableProxy: admin cannot fallback to proxy target\");\n super._beforeFallback();\n }\n\n function _getAdmin() internal view virtual override returns (address) {\n return _ADMIN;\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "evmVersion": "cancun", + "outputSelection": { + "*": { + "*": [ + "storageLayout", + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "evm.gasEstimates" + ], + "": ["ast"] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} diff --git a/deployments/bsctestnet_addresses.json b/deployments/bsctestnet_addresses.json index 59807c544..135415949 100644 --- a/deployments/bsctestnet_addresses.json +++ b/deployments/bsctestnet_addresses.json @@ -48,10 +48,10 @@ "CheckpointView_From_WhitePaperInterestRateModel_base200bps_slope1000bps_bpy10512000_To_bpy21024000_At_1744097580": "0xc8dC4a0a29e2423664556a31349Da3FF26850e8D", "CheckpointView_From_WhitePaperInterestRateModel_base200bps_slope1000bps_bpy21024000_To_bpy42048000_At_1748243100": "0x0F8F7633AdBea7025107421A5FBe354219B33FaF", "CheckpointView_From_WhitePaperInterestRateModel_base200bps_slope1000bps_bpy42048000_To_bpy70080000_At_1762741500": "0x4048c69928993023eD5D3fA9Da8708FfB4a21fe8", - "ComptrollerLens": "0x72dCB93F8c3fB00D31076e93b6E87C342A3eCC9c", + "ComptrollerLens": "0xdBD0992dEd0a1EC14CE0532e60ea023F79372eD9", "DefaultProxyAdmin": "0x7877ffd62649b6a1557b55d4c20fcbab17344c91", "ETH": "0x98f7A83361F7Ac8765CcEBAB1425da6b341958a7", - "FlashLoanFacet": "0x32348c5bB52E5468A11901e70BdE061192feCAf4", + "FlashLoanFacet": "0x694ee0149bE810F68aEbf3D7969a79D760769B18", "JumpRateModel_base0bps_slope1000bps_jump10900bps_kink8000bps_bpy21024000": "0xb1993AA3E9ee53D37096C58a4B86A8B1B6ED2F8e", "JumpRateModel_base0bps_slope1000bps_jump10900bps_kink8000bps_bpy42048000": "0x18A31286b462345A21Eb467c67e1C6282fa8E852", "JumpRateModel_base0bps_slope1000bps_jump10900bps_kink8000bps_bpy70080000": "0x66d8Ac8ef8C5A46909343be425b3Ed1C8b9c9373", @@ -100,7 +100,7 @@ "Liquidator": "0x55AEABa76ecf144031Ef64E222166eb28Cb4865F", "Liquidator_Implementation": "0x91070E5b5Ff60a6c122740EB326D1f80E9f470e7", "Liquidator_Proxy": "0x55AEABa76ecf144031Ef64E222166eb28Cb4865F", - "MarketFacet": "0x8e0e15C99Ab0985cB39B2FE36532E5692730eBA9", + "MarketFacet": "0xE160Afd62cAE8FCB16F6b702B325883dd80358d4", "MockFDUSD": "0xcF27439fA231af9931ee40c4f27Bb77B83826F3C", "MockPT-USDe-30Oct2025": "0x0c98334aCF440b9936D9cc1d99dc1A77bf26a93B", "MockPT-clisBNB-25JUN2026": "0x60825e8eBbed5C32c1DAA7eA68ceCA70BEA65040", @@ -117,7 +117,7 @@ "PegStability_USDT": "0xB21E69eef4Bc1D64903fa28D9b32491B1c0786F1", "PegStability_USDT_Implementation": "0xDDa903294fB71141302aD3Bf2AF37dD6Cbd5DBbF", "PegStability_USDT_Proxy": "0xB21E69eef4Bc1D64903fa28D9b32491B1c0786F1", - "PolicyFacet": "0xf8d94ef23c1188f8ab1009E56D558d7834d1F019", + "PolicyFacet": "0xDAfA77ED8b2CdF4dBE2D1aB27770eDE6A4a54463", "Prime": "0xe840F8EC2Dc50E7D22e5e2991975b9F6e34b62Ad", "PrimeLiquidityProvider": "0xAdeddc73eAFCbed174e6C400165b111b0cb80B7E", "PrimeLiquidityProviderTest": "0x7a780FbBa026568025a82101De65863A94CcD8f7", @@ -127,11 +127,11 @@ "PrimeLiquidityProvider_Proxy": "0xAdeddc73eAFCbed174e6C400165b111b0cb80B7E", "Prime_Implementation": "0x3C439A567C0f66b3D2Ca682327fC303Ec3Fb82D9", "Prime_Proxy": "0xe840F8EC2Dc50E7D22e5e2991975b9F6e34b62Ad", - "RewardFacet": "0x0bc7922Cc08Ea32E196d25805558a84dF54beC6a", + "RewardFacet": "0x977515f4043111ba5e44C09D3Af071ba5B9B34a1", "SXP": "0x75107940Cf1121232C0559c747A986DEfbc69DA9", "SetCheckpointBsctestnet": "0x69B83Bf4e8501D97217b545ce4151b62a5b550c9", - "SetterFacet": "0x4fc4C41388237D13A430879417f143EF54e5BB05", - "SnapshotLens": "0xBe9174A13577B016280aEc20a3b369C5BA272241", + "SetterFacet": "0x38DC0fcEC79675c41f3e461797A7dd99EF3baC6E", + "SnapshotLens": "0x88bB0AF511B5AB585460E7c36150Db82c28D9E5E", "SwapRouterCorePool": "0x83edf1deE1B730b7e8e13C00ba76027D63a51ac0", "SwapRouterDefi": "0x76B88ff4579B35D2722B7383b9B9ce831dc89B72", "SwapRouterGamefi": "0xFdeBF4530F9c7d352ffFE88cd0e96C8Bb7391BD9", @@ -152,7 +152,7 @@ "USDC": "0x16227D60f7a0e586C66B005219dfc887D13C9531", "USDT": "0xA11c8D9DC9b66E209Ef60F0C8D969D3CD988782c", "Unitroller": "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D", - "Unitroller_Implementation": "0x1774f993861B14B7C3963F3e09f67cfBd2B32198", + "Unitroller_Implementation": "0xf00Ba2930E43C96719Ca40c8B5a48F4c9A004c52", "Unitroller_Proxy": "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D", "VAI": "0x5fFbE5302BadED40941A403228E6AD03f93752d9", "VAIVault": "0x5c1c23ac038059c7B4EC1659728c166facab590b", @@ -172,7 +172,7 @@ "VRTVaultProxy_Proxy": "0x1ffD1b8B67A1AE0C189c734B0F58B0954522FF71", "VTreasury": "0x8b293600c50d6fbdc6ed4251cc75ece29880276f", "VaiUnitroller": "0xf70C3C6b749BbAb89C081737334E74C9aFD4BE16", - "VaiUnitroller_Implementation": "0xC1CE7174D58f177fd2b418292A6E60CDE9bACF78", + "VaiUnitroller_Implementation": "0xd2848305b0ee7646C930240D79549D50d6Ed024F", "VaiUnitroller_Proxy": "0xf70C3C6b749BbAb89C081737334E74C9aFD4BE16", "VenusLens": "0x969a45F1bb5Ba4037CB44664135862D0c2226F89", "WBETH": "0xf9F98365566F4D55234f24b99caA1AfBE6428D44", diff --git a/package.json b/package.json index 58b4b5bc6..3790df764 100644 --- a/package.json +++ b/package.json @@ -75,7 +75,7 @@ "@types/node": "^18.7.1", "@typescript-eslint/eslint-plugin": "^5.40.0", "@typescript-eslint/parser": "^5.40.0", - "@venusprotocol/oracle": "2.10.0", + "@venusprotocol/oracle": "2.15.0", "bignumber.js": "^9.1.2", "chai": "^4.3.6", "eslint": "^8.25.0", diff --git a/script/deploy/comptroller/facet-cut-params-generator.ts b/script/deploy/comptroller/facet-cut-params-generator.ts index 00a1e1c67..a6c97e21b 100644 --- a/script/deploy/comptroller/facet-cut-params-generator.ts +++ b/script/deploy/comptroller/facet-cut-params-generator.ts @@ -1,5 +1,5 @@ import fs from "fs"; -import { ethers } from "hardhat"; +import { deployments, ethers, network } from "hardhat"; import { FacetCutAction, getSelectors } from "./diamond"; @@ -8,96 +8,220 @@ import { FacetCutAction, getSelectors } from "./diamond"; * to add diamond facets */ -// Insert the addresses of the deployed facets to generate thecut params according for the same. -const facetsAddresses = { - MarketFacet: "", - PolicyFacet: "", - RewardFacet: "", - SetterFacet: "", -}; +type FacetName = "MarketFacet" | "PolicyFacet" | "RewardFacet" | "SetterFacet" | "FlashLoanFacet" | "FacetBase"; +type CutEntry = [string, number, string[]]; -// Set actions to the cut params to perform -// i.e. Add, Remove, Replace function selectors in the mapping. -const facetsActions = { - MarketFacet: FacetCutAction.Add, - PolicyFacet: FacetCutAction.Add, - RewardFacet: FacetCutAction.Add, - SetterFacet: FacetCutAction.Add, -}; +// FacetBase is a base contract whose selectors are inlined into the other facets. Each +// IFacetBase selector is routed to whichever concrete facet currently owns it on-chain so +// it rides along in that facet's cut entry. Anything not currently attached to a known +// facet falls into this placeholder for manual reassignment before submitting the cut. +const FACETBASE_PLACEHOLDER = "*FacetBase"; -// Set interfaces for the setters to generate function selectors from -const FacetsInterfaces = { +// Interfaces used to derive function selectors for each facet. +const FacetsInterfaces: Record = { MarketFacet: "IMarketFacet", PolicyFacet: "IPolicyFacet", RewardFacet: "IRewardFacet", SetterFacet: "ISetterFacet", + FlashLoanFacet: "IFlashLoanFacet", + FacetBase: "IFacetBase", }; -// Facets for which cute params need to generate -const FacetNames = ["MarketFacet", "PolicyFacet", "RewardFacet", "SetterFacet"]; +// Order matters: earlier facets claim shared selectors (inlined FacetBase methods) first. +const FacetNames = Object.keys(FacetsInterfaces) as FacetName[]; -// Name of the file to write the cut-params -const jsonFileName = "cur-params-test"; +const jsonFileName = `cut-params-${network.name}`; + +async function fetchContractName(address: string, chainId: number, apiKey: string): Promise { + const url = `https://api.etherscan.io/v2/api?chainid=${chainId}&module=contract&action=getsourcecode&address=${address}&apikey=${apiKey}`; + const delays = [500, 1500, 4500]; + let lastError: Error | undefined; + for (let attempt = 0; attempt <= delays.length; attempt++) { + try { + const res = await fetch(url); + if (!res.ok) throw new Error(`status ${res.status}`); + const json = (await res.json()) as { result?: Array<{ ContractName?: string }> }; + const name = json.result?.[0]?.ContractName; + if (!name) throw new Error("no contract name in response"); + return name; + } catch (e) { + lastError = e as Error; + if (attempt < delays.length) await new Promise(r => setTimeout(r, delays[attempt])); + } + } + throw new Error(`failed to get contract name for ${address}: ${lastError?.message}`); +} async function generateCutParams() { - const cut: any = []; - - for (const FacetName of FacetNames) { - const FacetInterface = await ethers.getContractAt(FacetsInterfaces[FacetName], facetsAddresses[FacetName]); - - switch (facetsActions[FacetName]) { - case FacetCutAction.Add: - cut.push({ - facetAddress: facetsAddresses[FacetName], - action: FacetCutAction.Add, - functionSelectors: getSelectors(FacetInterface), - }); - break; - case FacetCutAction.Remove: - cut.push({ - facetAddress: ethers.constants.AddressZero, - action: FacetCutAction.Remove, - functionSelectors: getSelectors(FacetInterface), - }); - break; - case FacetCutAction.Replace: - cut.push({ - facetAddress: facetsAddresses[FacetName], - action: FacetCutAction.Replace, - functionSelectors: getSelectors(FacetInterface), - }); - break; - default: - break; + const comptrollerDeployment = await deployments.get("Unitroller"); + const diamondAddress = comptrollerDeployment.address; + const diamond = await ethers.getContractAt("Diamond", diamondAddress); + const currentFacets = await diamond.facets(); + + // Resolve new facet addresses from hardhat-deploy artifacts (just-deployed). FacetBase + // has no on-chain instance, so it stays as the manual-reassignment placeholder. + const newFacetAddresses = new Map(); + for (const facetName of FacetNames) { + if (facetName === "FacetBase") { + newFacetAddresses.set(facetName, FACETBASE_PLACEHOLDER); + continue; } + const dep = await deployments.get(facetName); + newFacetAddresses.set(facetName, dep.address); } - function getFunctionSelector(selectors: any) { - const functionSelector: any = []; - for (let i = 0; i < selectors.length; i++) { - if (selectors[i][0] == "0") { - functionSelector.push(selectors[i]); + // Map every currently-deployed selector to the facet address that owns it. + const selectorToCurrentFacet = new Map(); + for (const f of currentFacets) { + for (const sel of f.functionSelectors) { + selectorToCurrentFacet.set(sel.toLowerCase(), f.facetAddress); + } + } + + // Resolve the new selectors for each facet from its interface, and build a + // selector → "fnName(types)" map so the diff file can show what each selector is. + const newSelectorsByFacet = new Map(); + const signatureBySelector = new Map(); + for (const facetName of FacetNames) { + const addr = newFacetAddresses.get(facetName)!; + const ifaceAddress = addr === FACETBASE_PLACEHOLDER ? ethers.constants.AddressZero : addr; + const iface = await ethers.getContractAt(FacetsInterfaces[facetName], ifaceAddress); + const selectors = (getSelectors(iface) as string[]).map(s => s.toLowerCase()); + newSelectorsByFacet.set(facetName, selectors); + for (const sig of Object.keys(iface.interface.functions)) { + if (sig === "init(bytes)") continue; + const sel = iface.interface.getSighash(sig).toLowerCase(); + if (!signatureBySelector.has(sel)) signatureBySelector.set(sel, sig); + } + } + + // Identify which currently-deployed facet backs each new facet by querying Etherscan v2 + // for the verified ContractName at each on-chain address. + const apiKey = process.env.ETHERSCAN_API_KEY; + if (!apiKey) throw new Error("ETHERSCAN_API_KEY env var is required"); + const chainId = network.config.chainId; + if (!chainId) throw new Error(`network.config.chainId is not set for network "${network.name}"`); + + const knownFacetNames = new Set(FacetNames); + const oldFacetAddressByName = new Map(); + const oldFacetNameByAddress = new Map(); + for (const f of currentFacets) { + const name = await fetchContractName(f.facetAddress, chainId, apiKey); + if (knownFacetNames.has(name)) { + const fname = name as FacetName; + oldFacetAddressByName.set(fname, f.facetAddress); + oldFacetNameByAddress.set(f.facetAddress, fname); + } + } + + // Redistribute IFacetBase selectors to whichever concrete facet currently owns them + // on-chain. Inherited selectors get attached to the deployed contract's address (not + // FacetBase, which has no on-chain instance), so we follow that same attribution. + const facetBaseSelectors = newSelectorsByFacet.get("FacetBase") ?? []; + const remainingFacetBaseSelectors: string[] = []; + for (const sel of facetBaseSelectors) { + const currentOwner = selectorToCurrentFacet.get(sel); + const currentOwnerFacet = currentOwner ? oldFacetNameByAddress.get(currentOwner) : undefined; + if (currentOwnerFacet && currentOwnerFacet !== "FacetBase") { + const list = newSelectorsByFacet.get(currentOwnerFacet)!; + if (!list.includes(sel)) list.push(sel); + } else { + remainingFacetBaseSelectors.push(sel); + } + } + newSelectorsByFacet.set("FacetBase", remainingFacetBaseSelectors); + + const cut: CutEntry[] = []; + // Each selector may appear in at most one cut entry; later facets defer to earlier ones. + const claimedInCut = new Set(); + + type DiffChange = { + selector: string; + signature: string; + facet: FacetName; + oldAddress?: string; + newAddress: string; + }; + type DiffRemoved = { + selector: string; + signature: string; + oldAddress: string; + oldFacet?: FacetName; + }; + const added: DiffChange[] = []; + const replaced: DiffChange[] = []; + + for (const facetName of FacetNames) { + const newFacetAddress = newFacetAddresses.get(facetName)!; + const newSelectors = newSelectorsByFacet.get(facetName)!; + + const replaceSelectors: string[] = []; + const addSelectors: string[] = []; + for (const sel of newSelectors) { + if (claimedInCut.has(sel)) continue; + claimedInCut.add(sel); + const signature = signatureBySelector.get(sel) ?? "unknown"; + const oldAddress = selectorToCurrentFacet.get(sel); + if (oldAddress) { + replaceSelectors.push(sel); + replaced.push({ selector: sel, signature, facet: facetName, oldAddress, newAddress: newFacetAddress }); } else { - break; + addSelectors.push(sel); + added.push({ selector: sel, signature, facet: facetName, newAddress: newFacetAddress }); } } - return functionSelector; + + if (replaceSelectors.length > 0) { + cut.push([newFacetAddress, FacetCutAction.Replace, replaceSelectors]); + } + if (addSelectors.length > 0) { + cut.push([newFacetAddress, FacetCutAction.Add, addSelectors]); + } } - function makeCutParam(cut: any) { - const cutParams = []; - for (let i = 0; i < cut.length; i++) { - const arr: any = new Array(3); - arr[0] = cut[i].facetAddress; - arr[1] = cut[i].action; - arr[2] = getFunctionSelector(cut[i].functionSelectors); - cutParams.push(arr); + // Selectors that live on an old version of an upgraded facet but are absent from the + // new layout must be Removed, otherwise diamondCut would leave them dangling. + const oldUpgradedAddresses = new Set(oldFacetAddressByName.values()); + const removeSelectors: string[] = []; + const removed: DiffRemoved[] = []; + for (const f of currentFacets) { + if (!oldUpgradedAddresses.has(f.facetAddress)) continue; + for (const sel of f.functionSelectors) { + const s = sel.toLowerCase(); + if (claimedInCut.has(s)) continue; + removeSelectors.push(s); + removed.push({ + selector: s, + signature: signatureBySelector.get(s) ?? "unknown", + oldAddress: f.facetAddress, + oldFacet: oldFacetNameByAddress.get(f.facetAddress), + }); } - return cutParams; } - const cutParams = { cutParams: makeCutParam(cut) }; + if (removeSelectors.length > 0) { + cut.push([ethers.constants.AddressZero, FacetCutAction.Remove, removeSelectors]); + } + const cutParams = { cutParams: cut }; fs.writeFileSync(`./${jsonFileName}.json`, JSON.stringify(cutParams, null, 4)); + + const diff = { + summary: { + added: added.length, + replaced: replaced.length, + removed: removed.length, + }, + added, + replaced, + removed, + }; + const diffFileName = `cut-diff-${network.name}`; + fs.writeFileSync(`./${diffFileName}.json`, JSON.stringify(diff, null, 4)); + + console.log("Cut params generated:"); + console.log(` - ${jsonFileName}.json`); + console.log(` - ${diffFileName}.json (added=${added.length} replaced=${replaced.length} removed=${removed.length})`); + console.log("Note: New FacetBase selectors should be manually assigned to their respective setter facets."); return cutParams; } diff --git a/tests/hardhat/Comptroller/Diamond/assetListTest.ts b/tests/hardhat/Comptroller/Diamond/assetListTest.ts index a85104aca..3998d931c 100644 --- a/tests/hardhat/Comptroller/Diamond/assetListTest.ts +++ b/tests/hardhat/Comptroller/Diamond/assetListTest.ts @@ -10,6 +10,7 @@ import { ComptrollerLens__factory, ComptrollerMock, IAccessControlManagerV5, + IDeviationBoundedOracle, PriceOracle, Unitroller, VBep20Immutable, @@ -70,6 +71,9 @@ describe("Comptroller: assetListTest", () => { await comptroller._setAccessControl(accessControl.address); await comptroller._setComptrollerLens(comptrollerLens.address); await comptroller._setPriceOracle(oracle.address); + const dbo = await smock.fake("IDeviationBoundedOracle"); + dbo.getBoundedPricesView.returns([convertToUnit("1", 18), convertToUnit("1", 18)]); + await comptroller.setDeviationBoundedOracle(dbo.address); const names = ["OMG", "ZRX", "BAT", "sketch"]; const [OMG, ZRX, BAT, SKT] = await Promise.all( names.map(async name => { diff --git a/tests/hardhat/Comptroller/Diamond/comptrollerTest.ts b/tests/hardhat/Comptroller/Diamond/comptrollerTest.ts index 635d8be7d..d5ab0959f 100644 --- a/tests/hardhat/Comptroller/Diamond/comptrollerTest.ts +++ b/tests/hardhat/Comptroller/Diamond/comptrollerTest.ts @@ -13,6 +13,7 @@ import { ComptrollerMock, EIP20Interface, IAccessControlManagerV5, + IDeviationBoundedOracle, PriceOracle, Unitroller, VAIController, @@ -26,6 +27,7 @@ chai.use(smock.matchers); type SimpleComptrollerFixture = { oracle: FakeContract; + dbo: FakeContract; accessControl: FakeContract; comptrollerLens: MockContract; unitroller: Unitroller; @@ -47,15 +49,23 @@ async function deploySimpleComptroller(): Promise { await comptroller._setAccessControl(accessControl.address); await comptroller._setComptrollerLens(comptrollerLens.address); await comptroller._setPriceOracle(oracle.address); + + const dbo = await smock.fake("IDeviationBoundedOracle"); + await comptroller.setDeviationBoundedOracle(dbo.address); + const vToken = await smock.fake("VToken"); - return { oracle, comptroller, unitroller, comptrollerLens, accessControl, vToken }; + return { oracle, dbo, comptroller, unitroller, comptrollerLens, accessControl, vToken }; } function configureOracle(oracle: FakeContract) { oracle.getUnderlyingPrice.returns(convertToUnit(1, 18)); } +function configureDeviationBoundedOracle(dbo: FakeContract) { + dbo.getBoundedPricesView.returns([convertToUnit(1, 18), convertToUnit(1, 18)]); +} + async function configureVToken(vToken: FakeContract, unitroller?: ComptrollerMock) { if (unitroller === undefined) { const result = await deployDiamond(""); @@ -350,6 +360,58 @@ describe("Comptroller", () => { }); }); + describe("setDeviationBoundedOracle", () => { + let comptroller: ComptrollerMock; + let accessControl: FakeContract; + let dbo: FakeContract; + + beforeEach(async () => { + ({ comptroller, accessControl } = await loadFixture(deploySimpleComptroller)); + dbo = await smock.fake("IDeviationBoundedOracle"); + }); + + it("fails if ACM does not allow the call", async () => { + accessControl.isAllowedToCall.returns(false); + await expect(comptroller.setDeviationBoundedOracle(dbo.address)).to.be.revertedWith("access denied"); + accessControl.isAllowedToCall.returns(true); + }); + + it("fails if zero address is passed", async () => { + // First set a valid DBO so compareAddress doesn't fire on address(0) → address(0) + await comptroller.setDeviationBoundedOracle(dbo.address); + await expect(comptroller.setDeviationBoundedOracle(constants.AddressZero)).to.be.revertedWith( + "can't be zero address", + ); + }); + + it("should revert on same value", async () => { + const currentDbo = await comptroller.deviationBoundedOracle(); + await expect(comptroller.setDeviationBoundedOracle(currentDbo)).to.be.revertedWith( + "old address is same as new address", + ); + }); + + it("sets DBO and emits NewDeviationBoundedOracle event", async () => { + const oldDbo = await comptroller.deviationBoundedOracle(); + expect(await comptroller.callStatic.setDeviationBoundedOracle(dbo.address)).to.equal( + ComptrollerErrorReporter.Error.NO_ERROR, + ); + await expect(comptroller.setDeviationBoundedOracle(dbo.address)) + .to.emit(comptroller, "NewDeviationBoundedOracle") + .withArgs(oldDbo, dbo.address); + expect(await comptroller.deviationBoundedOracle()).to.equal(dbo.address); + }); + + it("allows updating to a new DBO address", async () => { + await comptroller.setDeviationBoundedOracle(dbo.address); + const newDbo = await smock.fake("IDeviationBoundedOracle"); + await expect(comptroller.setDeviationBoundedOracle(newDbo.address)) + .to.emit(comptroller, "NewDeviationBoundedOracle") + .withArgs(dbo.address, newDbo.address); + expect(await comptroller.deviationBoundedOracle()).to.equal(newDbo.address); + }); + }); + describe("_setCloseFactor", () => { let comptroller: ComptrollerMock; @@ -955,13 +1017,16 @@ describe("Comptroller", () => { describe("borrow", () => { let comptrollerLens: FakeContract; + let dbo: FakeContract; beforeEach(async () => { const contracts = await loadFixture(deploy); + dbo = contracts.dbo; comptrollerLens = contracts.comptrollerLens; // ({ comptroller, oracle, vToken } = await loadFixture(deploy)); configureVToken(contracts.vToken, contracts.unitroller); configureOracle(contracts.oracle); + configureDeviationBoundedOracle(dbo); }); it("allows borrowing if cap is not reached", async () => { diff --git a/tests/hardhat/Comptroller/Diamond/deviationBoundedOracleTest.ts b/tests/hardhat/Comptroller/Diamond/deviationBoundedOracleTest.ts new file mode 100644 index 000000000..48a3c03ef --- /dev/null +++ b/tests/hardhat/Comptroller/Diamond/deviationBoundedOracleTest.ts @@ -0,0 +1,2188 @@ +import { FakeContract, MockContract, smock } from "@defi-wonderland/smock"; +import { loadFixture, setBalance } from "@nomicfoundation/hardhat-network-helpers"; +import chai from "chai"; +import { Signer } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; + +import { + ComptrollerLens, + ComptrollerLens__factory, + ComptrollerMock, + IAccessControlManagerV8, + IDeviationBoundedOracle, + PriceOracle, + Unitroller, + VAIController, + VToken, +} from "../../../../typechain"; +import { ComptrollerErrorReporter } from "../../util/Errors"; +import { deployDiamond } from "./scripts/deploy"; + +const { expect } = chai; +chai.use(smock.matchers); + +const { Error } = ComptrollerErrorReporter; + +// --------------------------------------------------------------------------- +// Constants used throughout the test suite +// --------------------------------------------------------------------------- +const SPOT_PRICE = parseUnits("1", 18); // $1 +const BOUNDED_COLLATERAL_PRICE = parseUnits("0.8", 18); // $0.80 +const BOUNDED_DEBT_PRICE = parseUnits("1.2", 18); // $1.20 +const CF = parseUnits("0.8", 18); // 80 % +const LT = parseUnits("0.9", 18); // 90 % +const EXCHANGE_RATE = parseUnits("1", 18); // 1:1 +const COLLATERAL_BALANCE = parseUnits("1000", 8); // 1 000 vTokens (8 decimals) +const LIQUIDATION_INCENTIVE = parseUnits("1.1", 18); +const CLOSE_FACTOR = parseUnits("0.5", 18); + +/* + * Math reference (all Exp mantissa arithmetic, truncated to uint): + * + * tokensToDenom = CF * exchangeRate * collateralPrice + * sumCollateral = tokensToDenom.mantissa * vTokenBalance / 1e18 + * + * At SPOT ($1): + * tokensToDenom = 0.8 * 1 * 1 = 0.8e18 + * sumCollateral = 0.8e18 * 1000e8 / 1e18 = 800e8 + * sumBorrow = 1 * borrowBalance + * + * At BOUNDED (collateral $0.80, debt $1.20): + * tokensToDenom = 0.8 * 1 * 0.8 = 0.64e18 + * sumCollateral = 0.64e18 * 1000e8 / 1e18 = 640e8 + * sumBorrow = 1.2 * borrowBalance + * + * At LT path (spot prices always, LT=0.9): + * tokensToDenom = 0.9 * 1 * 1 = 0.9e18 + * sumCollateral = 0.9e18 * 1000e8 / 1e18 = 900e8 + * sumBorrow = 1 * borrowBalance + */ + +// --------------------------------------------------------------------------- +// Types +// --------------------------------------------------------------------------- +type DboFixture = { + comptroller: ComptrollerMock; + unitroller: Unitroller; + comptrollerLens: MockContract; + oracle: FakeContract; + dbo: FakeContract; + accessControl: FakeContract; + vTokenA: FakeContract; // collateral token + vTokenB: FakeContract; // borrow token + vaiController: FakeContract; + root: Signer; + user: Signer; + liquidator: Signer; +}; + +// --------------------------------------------------------------------------- +// Shared fixture — only does EVM-state setup (deploy, support markets, etc.) +// The .returns() calls on fakes are done in configureFakes() below. +// --------------------------------------------------------------------------- +async function deployDboFixture(): Promise { + const [root, user, liquidator] = await ethers.getSigners(); + + // --- Deploy Diamond Comptroller --- + const result = await deployDiamond(""); + const unitroller = result.unitroller; + const comptroller = await ethers.getContractAt("ComptrollerMock", unitroller.address); + + // --- Access control --- + const accessControl = await smock.fake("IAccessControlManagerV8"); + accessControl.isAllowedToCall.returns(true); + await comptroller._setAccessControl(accessControl.address); + + // --- Real ComptrollerLens via smock.mock (so we can spy) --- + const LensFactory = await smock.mock("ComptrollerLens"); + const comptrollerLens = await LensFactory.deploy(); + await comptroller._setComptrollerLens(comptrollerLens.address); + + // --- Spot oracle --- + const oracle = await smock.fake("contracts/Oracle/PriceOracle.sol:PriceOracle"); + oracle.getUnderlyingPrice.returns(SPOT_PRICE); + await comptroller._setPriceOracle(oracle.address); + + // --- DBO fake --- + const dbo = await smock.fake("IDeviationBoundedOracle"); + dbo.getBoundedCollateralPriceView.returns(BOUNDED_COLLATERAL_PRICE); + dbo.getBoundedDebtPriceView.returns(BOUNDED_DEBT_PRICE); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, BOUNDED_DEBT_PRICE]); + await comptroller.setDeviationBoundedOracle(dbo.address); + + // --- VAI controller fake --- + const vaiController = await smock.fake("VAIController"); + vaiController.getVAIRepayAmount.returns(0); + await comptroller._setVAIController(vaiController.address); + + // --- Close factor --- + await comptroller._setCloseFactor(CLOSE_FACTOR); + + // --- vTokenA (collateral) --- + const vTokenA = await smock.fake("VToken"); + vTokenA.isVToken.returns(true); + vTokenA.comptroller.returns(comptroller.address); + vTokenA.exchangeRateStored.returns(EXCHANGE_RATE); + vTokenA.totalSupply.returns(parseUnits("1000000", 8)); + vTokenA.totalBorrows.returns(0); + vTokenA.borrowIndex.returns(parseUnits("1", 18)); + vTokenA.borrowBalanceStored.returns(0); + vTokenA.getAccountSnapshot.returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + + await comptroller._supportMarket(vTokenA.address); + await comptroller._setMarketSupplyCaps([vTokenA.address], [parseUnits("1000000", 18)]); + await comptroller._setMarketBorrowCaps([vTokenA.address], [parseUnits("1000000", 18)]); + await comptroller["setCollateralFactor(address,uint256,uint256)"](vTokenA.address, CF, LT); + await comptroller["setLiquidationIncentive(address,uint256)"](vTokenA.address, LIQUIDATION_INCENTIVE); + + // --- vTokenB (borrow market) --- + const vTokenB = await smock.fake("VToken"); + vTokenB.isVToken.returns(true); + vTokenB.comptroller.returns(comptroller.address); + vTokenB.exchangeRateStored.returns(EXCHANGE_RATE); + vTokenB.totalSupply.returns(parseUnits("1000000", 8)); + vTokenB.totalBorrows.returns(0); + vTokenB.borrowIndex.returns(parseUnits("1", 18)); + vTokenB.borrowBalanceStored.returns(0); + vTokenB.getAccountSnapshot.returns([0, 0, 0, EXCHANGE_RATE]); + + await comptroller._supportMarket(vTokenB.address); + await comptroller._setMarketSupplyCaps([vTokenB.address], [parseUnits("1000000", 18)]); + await comptroller._setMarketBorrowCaps([vTokenB.address], [parseUnits("1000000", 18)]); + await comptroller["setCollateralFactor(address,uint256,uint256)"](vTokenB.address, CF, LT); + await comptroller["setLiquidationIncentive(address,uint256)"](vTokenB.address, LIQUIDATION_INCENTIVE); + await comptroller.setIsBorrowAllowed(0, vTokenB.address, true); + await comptroller.setIsBorrowAllowed(0, vTokenA.address, true); + + // --- Fund vToken wallets so they can call the comptroller --- + await setBalance(await vTokenA.wallet.getAddress(), 10n ** 18n); + await setBalance(await vTokenB.wallet.getAddress(), 10n ** 18n); + + return { + comptroller, + unitroller, + comptrollerLens, + oracle, + dbo, + accessControl, + vTokenA, + vTokenB, + vaiController, + root, + user, + liquidator, + }; +} + +// --------------------------------------------------------------------------- +// configureFakes — reconfigure ALL fake return values after loadFixture +// --------------------------------------------------------------------------- +function configureFakes(fixture: DboFixture): void { + const { oracle, dbo, accessControl, vTokenA, vTokenB, vaiController, comptroller } = fixture; + + // Access control — reset clears any whenCalledWith overrides from prior tests + accessControl.isAllowedToCall.reset(); + accessControl.isAllowedToCall.returns(true); + + // Spot oracle + oracle.getUnderlyingPrice.reset(); + oracle.getUnderlyingPrice.returns(SPOT_PRICE); + + // DBO + dbo.getBoundedCollateralPriceView.reset(); + dbo.getBoundedCollateralPriceView.returns(BOUNDED_COLLATERAL_PRICE); + dbo.getBoundedDebtPriceView.reset(); + dbo.getBoundedDebtPriceView.returns(BOUNDED_DEBT_PRICE); + dbo.getBoundedPricesView.reset(); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, BOUNDED_DEBT_PRICE]); + dbo.updateProtectionState.reset(); + + // VAI controller + vaiController.getVAIRepayAmount.reset(); + vaiController.getVAIRepayAmount.returns(0); + + // vTokenA (collateral) + vTokenA.isVToken.reset(); + vTokenA.isVToken.returns(true); + vTokenA.comptroller.reset(); + vTokenA.comptroller.returns(comptroller.address); + vTokenA.exchangeRateStored.reset(); + vTokenA.exchangeRateStored.returns(EXCHANGE_RATE); + vTokenA.totalSupply.reset(); + vTokenA.totalSupply.returns(parseUnits("1000000", 8)); + vTokenA.totalBorrows.reset(); + vTokenA.totalBorrows.returns(0); + vTokenA.borrowIndex.reset(); + vTokenA.borrowIndex.returns(parseUnits("1", 18)); + vTokenA.borrowBalanceStored.reset(); + vTokenA.borrowBalanceStored.returns(0); + vTokenA.getAccountSnapshot.reset(); + vTokenA.getAccountSnapshot.returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + + // vTokenB (borrow market) + vTokenB.isVToken.reset(); + vTokenB.isVToken.returns(true); + vTokenB.comptroller.reset(); + vTokenB.comptroller.returns(comptroller.address); + vTokenB.exchangeRateStored.reset(); + vTokenB.exchangeRateStored.returns(EXCHANGE_RATE); + vTokenB.totalSupply.reset(); + vTokenB.totalSupply.returns(parseUnits("1000000", 8)); + vTokenB.totalBorrows.reset(); + vTokenB.totalBorrows.returns(0); + vTokenB.borrowIndex.reset(); + vTokenB.borrowIndex.returns(parseUnits("1", 18)); + vTokenB.borrowBalanceStored.reset(); + vTokenB.borrowBalanceStored.returns(0); + vTokenB.getAccountSnapshot.reset(); + vTokenB.getAccountSnapshot.returns([0, 0, 0, EXCHANGE_RATE]); +} + +// --------------------------------------------------------------------------- +// Helper: enter user into vTokenA market +// --------------------------------------------------------------------------- +async function enterCollateralMarket( + comptroller: ComptrollerMock, + vToken: FakeContract, + user: Signer, +): Promise { + await comptroller.connect(user).enterMarkets([vToken.address]); +} + +// --------------------------------------------------------------------------- +// Tests +// --------------------------------------------------------------------------- +describe("DeviationBoundedOracle Integration", () => { + // ========================================================================= + // Section A: Setup & DBO Configuration + // ========================================================================= + describe("A. Setup and DBO configuration", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("A.1 - setDeviationBoundedOracle stores the new DBO address", async () => { + const { comptroller } = fixture; + const dbo = await smock.fake("IDeviationBoundedOracle"); + await comptroller.setDeviationBoundedOracle(dbo.address); + expect(await comptroller.deviationBoundedOracle()).to.equal(dbo.address); + }); + + it("A.2 - setDeviationBoundedOracle rejects zero address", async () => { + const { comptroller } = fixture; + await expect(comptroller.setDeviationBoundedOracle(ethers.constants.AddressZero)).to.be.revertedWith( + "can't be zero address", + ); + }); + + it("A.3 - setDeviationBoundedOracle reverts when called by non-admin", async () => { + const { comptroller, user, accessControl } = fixture; + accessControl.isAllowedToCall.returns(false); + const dbo = await smock.fake("IDeviationBoundedOracle"); + await expect(comptroller.connect(user).setDeviationBoundedOracle(dbo.address)).to.be.reverted; + }); + + it("A.4 - fixture deploys two supported markets with correct CF and LT", async () => { + const { comptroller, vTokenA, vTokenB } = fixture; + const marketA = await comptroller.markets(vTokenA.address); + expect(marketA.collateralFactorMantissa).to.equal(CF); + expect(marketA.liquidationThresholdMantissa).to.equal(LT); + const marketB = await comptroller.markets(vTokenB.address); + expect(marketB.collateralFactorMantissa).to.equal(CF); + expect(marketB.liquidationThresholdMantissa).to.equal(LT); + }); + + it("A.5 - DBO fake returns expected bounded prices", async () => { + const { dbo, vTokenA } = fixture; + expect(await dbo.getBoundedCollateralPriceView(vTokenA.address)).to.equal(BOUNDED_COLLATERAL_PRICE); + expect(await dbo.getBoundedDebtPriceView(vTokenA.address)).to.equal(BOUNDED_DEBT_PRICE); + }); + }); + + // ========================================================================= + // Section B: borrowAllowed — CF path (state-changing) + // ========================================================================= + describe("B. borrowAllowed (CF path)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("B.1 - allows borrow when solvent at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // At bounded: sumCollateral = 640e8, sumBorrow = 1.2 * borrow + // Borrow 100e8 underlying: sumBorrow = 120e8 < 640e8 => solvent + const borrowAmount = parseUnits("100", 8); + vTokenB.totalBorrows.returns(0); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("B.2 - rejects borrow that would cause shortfall at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // At bounded: sumCollateral = 640e8 + // Borrow 600e8: sumBorrow = 1.2 * 600e8 = 720e8 > 640e8 => shortfall + const borrowAmount = parseUnits("600", 8); + vTokenB.totalBorrows.returns(0); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + + it("B.3 - calls _updateProtectionStates (dbo.updateProtectionState for each asset)", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.updateProtectionState.reset(); + const borrowAmount = parseUnits("10", 8); + vTokenB.totalBorrows.returns(0); + await comptroller.connect(vTokenB.wallet).borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenA.address); + }); + + it("B.4 - uses getBoundedPricesView for collateral valuation", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedPricesView.reset(); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, BOUNDED_DEBT_PRICE]); + const borrowAmount = parseUnits("10", 8); + vTokenB.totalBorrows.returns(0); + await comptroller.connect(vTokenB.wallet).borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(dbo.getBoundedPricesView).to.have.been.calledWith(vTokenA.address); + }); + + it("B.5 - uses getBoundedPricesView for debt valuation", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedPricesView.reset(); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, BOUNDED_DEBT_PRICE]); + const borrowAmount = parseUnits("10", 8); + vTokenB.totalBorrows.returns(0); + await comptroller.connect(vTokenB.wallet).borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(dbo.getBoundedPricesView).to.have.been.calledWith(vTokenA.address); + }); + + it("B.6 - auto-enters borrower into market when called from vToken", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + // User enters A as collateral but NOT B + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + expect(await comptroller.checkMembership(userAddr, vTokenB.address)).to.be.false; + + vTokenB.totalBorrows.returns(0); + await comptroller.connect(vTokenB.wallet).borrowAllowed(vTokenB.address, userAddr, parseUnits("10", 8)); + + expect(await comptroller.checkMembership(userAddr, vTokenB.address)).to.be.true; + }); + + it("B.7 - reverts if oracle price is 0 (PRICE_ERROR)", async () => { + const { comptroller, vTokenA, vTokenB, user, oracle, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + oracle.getUnderlyingPrice.whenCalledWith(vTokenB.address).returns(0); + dbo.getBoundedPricesView.whenCalledWith(vTokenB.address).returns([0, 0]); + vTokenB.totalBorrows.returns(0); + + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("10", 8)); + expect(errCode).to.equal(Error.PRICE_ERROR); + }); + + it("B.8 - reverts with borrow cap exceeded", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + vTokenB.totalBorrows.returns(parseUnits("1000000", 18)); + + await expect( + comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("1", 8)), + ).to.be.revertedWith("market borrow cap reached"); + }); + + it("B.9 - updates protection state for all entered assets (two markets)", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + // Also enter B + await enterCollateralMarket(comptroller, vTokenB, user); + + dbo.updateProtectionState.reset(); + vTokenB.totalBorrows.returns(0); + await comptroller + .connect(vTokenB.wallet) + .borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("10", 8)); + + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenA.address); + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenB.address); + }); + + it("B.10 - borrow that would succeed at spot but fails at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // At spot: sumCollateral = 800e8, borrow 700e8 => sumBorrow = 700e8 < 800e8 => solvent + // At bounded: sumCollateral = 640e8, sumBorrow = 1.2 * 700e8 = 840e8 > 640e8 => shortfall + const borrowAmount = parseUnits("700", 8); + vTokenB.totalBorrows.returns(0); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + + it("B.11 - borrow exactly at bounded capacity succeeds", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // sumCollateral = 640e8, need sumBorrow <= 640e8 + // sumBorrow = 1.2 * borrowAmount => borrowAmount = 640e8 / 1.2 = 533.333...e8 + // Use 533e8 which gives 1.2 * 533e8 = 639.6e8 < 640e8 => solvent + const borrowAmount = parseUnits("533", 8); + vTokenB.totalBorrows.returns(0); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("B.12 - returns PRICE_ERROR if bounded collateral price is 0", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedCollateralPriceView.returns(0); + dbo.getBoundedPricesView.returns([0, BOUNDED_DEBT_PRICE]); + vTokenB.totalBorrows.returns(0); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("10", 8)); + expect(errCode).to.equal(Error.PRICE_ERROR); + }); + + it("B.13 - returns PRICE_ERROR if bounded debt price is 0", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedDebtPriceView.returns(0); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, 0]); + vTokenB.totalBorrows.returns(0); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("10", 8)); + expect(errCode).to.equal(Error.PRICE_ERROR); + }); + }); + + // ========================================================================= + // Section C: redeemAllowed — CF path (state-changing) + // ========================================================================= + describe("C. redeemAllowed (CF path)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("C.1 - allows redeem when remaining collateral covers borrows at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // User has borrow of 100e8 on B + // After redeeming 100 vTokens, remaining vToken balance = 900e8 + // sumCollateral = 0.8 * 1 * 0.8 * 900e8 = 576e8 + // sumBorrow = 1.2 * 100e8 = 120e8 => solvent + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("100", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const redeemTokens = parseUnits("100", 8); + const errCode = await comptroller.callStatic.redeemAllowed(vTokenA.address, userAddr, redeemTokens); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("C.2 - rejects redeem that causes shortfall at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // User has 500e8 borrow on B + // sumCollateral = 0.8 * 1 * 0.8 * 1000e8 = 640e8 + // sumBorrow = 1.2 * 500e8 = 600e8 + // Redeem 200 vTokens: hypothetical adds tokensToDenom * 200e8 to borrows + // tokensToDenom = 0.64e18, add = 0.64 * 200e8 = 128e8 + // total borrows = 600e8 + 128e8 = 728e8 > 640e8 => shortfall + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("500", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const redeemTokens = parseUnits("200", 8); + const errCode = await comptroller.callStatic.redeemAllowed(vTokenA.address, userAddr, redeemTokens); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + + it("C.3 - calls updateProtectionState during redeemAllowed", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + dbo.updateProtectionState.reset(); + await comptroller.redeemAllowed(vTokenA.address, userAddr, parseUnits("10", 8)); + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenA.address); + }); + + it("C.4 - allows full redeem when no borrows exist", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + const errCode = await comptroller.callStatic.redeemAllowed(vTokenA.address, userAddr, COLLATERAL_BALANCE); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("C.5 - skips liquidity check if user is not in the market", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + // Do NOT enter market + const userAddr = await user.getAddress(); + + dbo.updateProtectionState.reset(); + const errCode = await comptroller.callStatic.redeemAllowed(vTokenA.address, userAddr, COLLATERAL_BALANCE); + expect(errCode).to.equal(Error.NO_ERROR); + // Since user is not in market, DBO should not be called + expect(dbo.updateProtectionState).to.not.have.been.called; + }); + + it("C.6 - uses bounded prices not spot for redeem liquidity check", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Borrow 600e8 on B + // At spot: sumCollateral=800e8, sumBorrow=600e8, redeem 100 adds 0.8*100e8=80e8 => 680e8 < 800e8 => OK + // At bounded: sumCollateral=640e8, sumBorrow=720e8, redeem 100 adds 0.64*100e8=64e8 => 784e8 > 640e8 => fail + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("600", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const errCode = await comptroller.callStatic.redeemAllowed(vTokenA.address, userAddr, parseUnits("100", 8)); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + + it("C.7 - allows zero-amount redeem", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + const errCode = await comptroller.callStatic.redeemAllowed(vTokenA.address, userAddr, 0); + expect(errCode).to.equal(Error.NO_ERROR); + }); + }); + + // ========================================================================= + // Section D: transferAllowed — CF path (state-changing) + // ========================================================================= + describe("D. transferAllowed (CF path)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("D.1 - allows transfer when remaining collateral covers borrows at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user, root } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // User has borrow of 100e8 on B + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("100", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // Transfer 100 vTokens => same as redeeming 100 vTokens from src + const errCode = await comptroller.callStatic.transferAllowed( + vTokenA.address, + userAddr, + await root.getAddress(), + parseUnits("100", 8), + ); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("D.2 - rejects transfer that causes shortfall at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user, root } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("500", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const errCode = await comptroller.callStatic.transferAllowed( + vTokenA.address, + userAddr, + await root.getAddress(), + parseUnits("200", 8), + ); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + + it("D.3 - calls updateProtectionState during transferAllowed", async () => { + const { comptroller, vTokenA, user, root, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + dbo.updateProtectionState.reset(); + await comptroller.transferAllowed(vTokenA.address, userAddr, await root.getAddress(), parseUnits("10", 8)); + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenA.address); + }); + + it("D.4 - allows transfer if src is not in the market", async () => { + const { comptroller, vTokenA, user, root, dbo } = fixture; + // Do NOT enter market + const userAddr = await user.getAddress(); + + dbo.updateProtectionState.reset(); + const errCode = await comptroller.callStatic.transferAllowed( + vTokenA.address, + userAddr, + await root.getAddress(), + COLLATERAL_BALANCE, + ); + expect(errCode).to.equal(Error.NO_ERROR); + expect(dbo.updateProtectionState).to.not.have.been.called; + }); + + it("D.5 - transfer that would succeed at spot but fails at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user, root } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Borrow 500e8 + // At spot: sumCollateral=800e8, sumBorrow=500e8. Transfer 300: adds 0.8*300e8=240e8 => 740e8 < 800e8 OK + // At bounded: sumCollateral=640e8, sumBorrow=600e8. Transfer 300: adds 0.64*300e8=192e8 => 792e8 > 640e8 FAIL + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("500", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const errCode = await comptroller.callStatic.transferAllowed( + vTokenA.address, + userAddr, + await root.getAddress(), + parseUnits("300", 8), + ); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + }); + + // ========================================================================= + // Section E: liquidateBorrowAllowed — LT path (view, no DBO) + // ========================================================================= + describe("E. liquidateBorrowAllowed (LT path, spot prices)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("E.1 - uses spot prices and LT, not bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + const liquidatorAddr = await liquidator.getAddress(); + + // At LT(0.9) and spot($1): sumCollateral = 0.9 * 1 * 1 * 1000e8 = 900e8 + // Borrow 950e8 => shortfall at LT + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("950", 8), EXCHANGE_RATE]); + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("950", 8)); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + dbo.getBoundedCollateralPriceView.reset(); + dbo.getBoundedDebtPriceView.reset(); + dbo.getBoundedPricesView.reset(); + + const errCode = await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + liquidatorAddr, + userAddr, + parseUnits("100", 8), + ); + expect(errCode).to.equal(Error.NO_ERROR); + // DBO bounded prices should NOT be called for LT path + expect(dbo.getBoundedCollateralPriceView).to.not.have.been.called; + expect(dbo.getBoundedDebtPriceView).to.not.have.been.called; + expect(dbo.getBoundedPricesView).to.not.have.been.called; + }); + + it("E.2 - does not call updateProtectionState", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("950", 8), EXCHANGE_RATE]); + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("950", 8)); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + dbo.updateProtectionState.reset(); + + await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + await liquidator.getAddress(), + userAddr, + parseUnits("100", 8), + ); + expect(dbo.updateProtectionState).to.not.have.been.called; + }); + + it("E.3 - fails with INSUFFICIENT_SHORTFALL when borrower has no LT shortfall", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // At LT: sumCollateral = 900e8, borrow 700e8 => liquidity = 200e8, no shortfall + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("700", 8), EXCHANGE_RATE]); + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("700", 8)); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const errCode = await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + await liquidator.getAddress(), + userAddr, + parseUnits("100", 8), + ); + expect(errCode).to.equal(Error.INSUFFICIENT_SHORTFALL); + }); + + it("E.4 - allows liquidation when borrower has LT shortfall", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // At LT: sumCollateral = 900e8, borrow 950e8 => shortfall = 50e8 + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("950", 8), EXCHANGE_RATE]); + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("950", 8)); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // closeFactor = 0.5, maxRepay = 0.5 * 950e8 = 475e8 + const errCode = await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + await liquidator.getAddress(), + userAddr, + parseUnits("100", 8), + ); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("E.5 - fails with TOO_MUCH_REPAY when repayAmount exceeds closeFactor * borrowBalance", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("950", 8), EXCHANGE_RATE]); + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("950", 8)); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // closeFactor * 950e8 = 475e8, try repaying 476e8 => TOO_MUCH_REPAY + const errCode = await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + await liquidator.getAddress(), + userAddr, + parseUnits("476", 8), + ); + expect(errCode).to.equal(17); // TOO_MUCH_REPAY + }); + + it("E.6 - forced liquidation bypasses LT shortfall check", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // No shortfall at LT + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("700", 8), EXCHANGE_RATE]); + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("700", 8)); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + await comptroller._setForcedLiquidation(vTokenB.address, true); + const errCode = await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + await liquidator.getAddress(), + userAddr, + parseUnits("100", 8), + ); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("E.7 - forced liquidation does not call DBO", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("100", 8)); + await comptroller._setForcedLiquidation(vTokenB.address, true); + + dbo.updateProtectionState.reset(); + dbo.getBoundedCollateralPriceView.reset(); + dbo.getBoundedDebtPriceView.reset(); + dbo.getBoundedPricesView.reset(); + + await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + await liquidator.getAddress(), + userAddr, + parseUnits("50", 8), + ); + + expect(dbo.updateProtectionState).to.not.have.been.called; + expect(dbo.getBoundedCollateralPriceView).to.not.have.been.called; + expect(dbo.getBoundedDebtPriceView).to.not.have.been.called; + expect(dbo.getBoundedPricesView).to.not.have.been.called; + }); + }); + + // ========================================================================= + // Section F: exitMarket — CF path (state-changing) + // ========================================================================= + describe("F. exitMarket (CF path)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("F.1 - allows exit when user has no borrows", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // Ensure getAccountSnapshot returns 0 borrow balance for the exiting token + vTokenA.getAccountSnapshot + .whenCalledWith(await user.getAddress()) + .returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + + const errCode = await comptroller.connect(user).callStatic.exitMarket(vTokenA.address); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("F.2 - rejects exit when user has nonzero borrow balance on the exiting token", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // User has borrow on vTokenA itself + vTokenA.getAccountSnapshot + .whenCalledWith(userAddr) + .returns([0, COLLATERAL_BALANCE, parseUnits("100", 8), EXCHANGE_RATE]); + + const errCode = await comptroller.connect(user).callStatic.exitMarket(vTokenA.address); + expect(errCode).to.equal(Error.NONZERO_BORROW_BALANCE); + }); + + it("F.3 - rejects exit when redeeming full balance causes shortfall at bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // User has borrows on B, trying to exit A (which is collateral) + // exitMarket calls redeemAllowedInternal(vTokenA, user, tokensHeld) + // This will check if redeeming ALL tokens causes shortfall + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("100", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // At bounded: sumCollateral=640e8, sumBorrow=120e8 + // Redeem all 1000e8 tokens: adds 0.64*1000e8=640e8 to borrows + // total borrows = 120e8 + 640e8 = 760e8 > 640e8 => shortfall + const errCode = await comptroller.connect(user).callStatic.exitMarket(vTokenA.address); + // exitMarket returns REJECTION when redeemAllowedInternal fails + expect(errCode).to.not.equal(Error.NO_ERROR); + }); + + it("F.4 - calls updateProtectionState during exit liquidity check", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("10", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + dbo.updateProtectionState.reset(); + await comptroller.connect(user).exitMarket(vTokenA.address); + // Should have been called because exitMarket uses CF path + expect(dbo.updateProtectionState).to.have.been.called; + }); + + it("F.5 - succeeds if user is not in the market", async () => { + const { comptroller, vTokenA, user } = fixture; + // Do NOT enter + const errCode = await comptroller.connect(user).callStatic.exitMarket(vTokenA.address); + expect(errCode).to.equal(Error.NO_ERROR); + }); + }); + + // ========================================================================= + // Section G: getBorrowingPower — CF view path (no updateProtectionState) + // ========================================================================= + describe("G. getBorrowingPower (CF view path)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("G.1 - returns liquidity based on bounded prices", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // No borrows: sumCollateral = 640e8 + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("640", 8)); + expect(shortfall).to.equal(0); + }); + + it("G.2 - returns shortfall when borrows exceed bounded collateral", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("700", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // sumCollateral = 640e8, sumBorrow = 1.2 * 700e8 = 840e8 + // shortfall = 840e8 - 640e8 = 200e8 + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.equal(parseUnits("200", 8)); + }); + + it("G.3 - does not call updateProtectionState (view function)", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.updateProtectionState.reset(); + await comptroller.getBorrowingPower(await user.getAddress()); + expect(dbo.updateProtectionState).to.not.have.been.called; + }); + + it("G.4 - reads DBO bounded price views", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedPricesView.reset(); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, BOUNDED_DEBT_PRICE]); + await comptroller.getBorrowingPower(await user.getAddress()); + expect(dbo.getBoundedPricesView).to.have.been.calledWith(vTokenA.address); + }); + + it("G.5 - accounts for VAI debt", async () => { + const { comptroller, vTokenA, user, vaiController } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // VAI debt of 100e18 is added to sumBorrows + vaiController.getVAIRepayAmount.whenCalledWith(userAddr).returns(parseUnits("100", 18)); + + // sumCollateral = 640e8, sumBorrow = 0 (no token borrows) + 100e18 (VAI) + // But 640e8 vs 100e18: VAI is in 18 decimals = 100e18 which is huge compared to 640e8 + // so there will be shortfall + const [err, , shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(shortfall).to.be.gt(0); + }); + + it("G.6 - returns zero values for account with no positions", async () => { + const { comptroller, user } = fixture; + const userAddr = await user.getAddress(); + + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.equal(0); + }); + }); + + // ========================================================================= + // Section H: getAccountLiquidity — LT view path (spot prices, no DBO) + // ========================================================================= + describe("H. getAccountLiquidity (LT view path)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("H.1 - uses spot prices with LT, not bounded prices", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + dbo.getBoundedCollateralPriceView.reset(); + dbo.getBoundedDebtPriceView.reset(); + dbo.getBoundedPricesView.reset(); + + // LT = 0.9, spot = $1, balance = 1000e8 + // sumCollateral = 0.9 * 1 * 1 * 1000e8 = 900e8 + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("900", 8)); + expect(shortfall).to.equal(0); + + // DBO bounded prices should NOT be called + expect(dbo.getBoundedCollateralPriceView).to.not.have.been.called; + expect(dbo.getBoundedDebtPriceView).to.not.have.been.called; + expect(dbo.getBoundedPricesView).to.not.have.been.called; + }); + + it("H.2 - returns shortfall at LT path when deeply underwater", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("950", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // sumCollateral_LT = 900e8, sumBorrow = 950e8 + // shortfall = 50e8 + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.equal(parseUnits("50", 8)); + }); + + it("H.3 - does not call updateProtectionState", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.updateProtectionState.reset(); + await comptroller.getAccountLiquidity(await user.getAddress()); + expect(dbo.updateProtectionState).to.not.have.been.called; + }); + + it("H.4 - solvent at LT but underwater at bounded CF", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Borrow 700e8: at LT(0.9, spot) collateral = 900e8 > 700e8 => solvent + // But at bounded CF: 640e8 < 840e8 => shortfall + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("700", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.be.gt(0); // Solvent at LT + expect(shortfall).to.equal(0); + + // But borrowing power (CF path) shows shortfall + const [, , bpShortfall] = await comptroller.getBorrowingPower(userAddr); + expect(bpShortfall).to.be.gt(0); + }); + + it("H.5 - returns zero for empty account", async () => { + const { comptroller, user } = fixture; + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(await user.getAddress()); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.equal(0); + }); + }); + + // ========================================================================= + // Section I: getHypotheticalAccountLiquidity — CF view path + // ========================================================================= + describe("I. getHypotheticalAccountLiquidity (CF view path)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("I.1 - hypothetical borrow uses bounded prices", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + const userAddr = await user.getAddress(); + + // Hypothetical borrow of 600e8 + // sumCollateral = 640e8 (bounded CF) + // hypothetical sumBorrow = 1.2 * 600e8 = 720e8 + // shortfall = 80e8 + const [err, liquidity, shortfall] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenB.address, + 0, + parseUnits("600", 8), + ); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.equal(parseUnits("80", 8)); + }); + + it("I.2 - hypothetical redeem uses bounded prices", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Hypothetical redeem of 500 vTokens from A + // sumCollateral = 640e8 + // Redeem 500e8: adds tokensToDenom * 500e8 to borrows = 0.64 * 500e8 = 320e8 + // total borrows = 0 + 320e8 = 320e8 < 640e8 => solvent + const [err, liquidity, shortfall] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenA.address, + parseUnits("500", 8), + 0, + ); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("320", 8)); // 640e8 - 320e8 + expect(shortfall).to.equal(0); + }); + + it("I.3 - does not call updateProtectionState", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.updateProtectionState.reset(); + await comptroller.getHypotheticalAccountLiquidity( + await user.getAddress(), + vTokenB.address, + 0, + parseUnits("100", 8), + ); + expect(dbo.updateProtectionState).to.not.have.been.called; + }); + + it("I.4 - reads DBO bounded price views for CF weighting", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedPricesView.reset(); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, BOUNDED_DEBT_PRICE]); + + await comptroller.getHypotheticalAccountLiquidity( + await user.getAddress(), + vTokenB.address, + 0, + parseUnits("100", 8), + ); + expect(dbo.getBoundedPricesView).to.have.been.calledWith(vTokenA.address); + }); + + it("I.5 - returns correct liquidity with no hypothetical changes", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + const [err, liquidity, shortfall] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + ethers.constants.AddressZero, + 0, + 0, + ); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("640", 8)); + expect(shortfall).to.equal(0); + }); + }); + + // ========================================================================= + // Section J: DBO disabled (zero address) + // ========================================================================= + describe("J. DBO returning zero prices (error handling)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("J.1 - getBorrowingPower returns PRICE_ERROR when DBO returns 0 for collateral", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedCollateralPriceView.returns(0); + dbo.getBoundedPricesView.returns([0, BOUNDED_DEBT_PRICE]); + const [err] = await comptroller.getBorrowingPower(await user.getAddress()); + expect(err).to.equal(Error.PRICE_ERROR); + }); + + it("J.2 - getBorrowingPower returns PRICE_ERROR when DBO returns 0 for debt", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedDebtPriceView.returns(0); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, 0]); + const [err] = await comptroller.getBorrowingPower(await user.getAddress()); + expect(err).to.equal(Error.PRICE_ERROR); + }); + + it("J.3 - getAccountLiquidity still works with spot oracle (LT path) regardless of DBO prices", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // Even if DBO returns 0, LT path doesn't use DBO at all + dbo.getBoundedCollateralPriceView.returns(0); + dbo.getBoundedDebtPriceView.returns(0); + dbo.getBoundedPricesView.returns([0, 0]); + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(await user.getAddress()); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("900", 8)); + expect(shortfall).to.equal(0); + }); + + it("J.4 - liquidateBorrowAllowed still works with LT path regardless of DBO prices", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + dbo.getBoundedCollateralPriceView.returns(0); + dbo.getBoundedDebtPriceView.returns(0); + dbo.getBoundedPricesView.returns([0, 0]); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("950", 8), EXCHANGE_RATE]); + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("950", 8)); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const errCode = await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + await liquidator.getAddress(), + userAddr, + parseUnits("100", 8), + ); + expect(errCode).to.equal(Error.NO_ERROR); + }); + }); + + // ========================================================================= + // Section K: Bounded price equals spot (DBO is pass-through) + // ========================================================================= + describe("K. Bounded prices equal spot prices (DBO pass-through)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + // Override DBO to return spot prices => same as no deviation + fixture.dbo.getBoundedCollateralPriceView.returns(SPOT_PRICE); + fixture.dbo.getBoundedDebtPriceView.returns(SPOT_PRICE); + fixture.dbo.getBoundedPricesView.returns([SPOT_PRICE, SPOT_PRICE]); + }); + + it("K.1 - getBorrowingPower matches spot-based CF calculation", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // At spot with CF=0.8: sumCollateral = 0.8 * 1 * 1 * 1000e8 = 800e8 + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(await user.getAddress()); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("800", 8)); + expect(shortfall).to.equal(0); + }); + + it("K.2 - borrowAllowed accepts borrow up to spot CF capacity", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // At spot: capacity = 800e8, borrow 799e8 => solvent + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("799", 8)); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("K.3 - borrowAllowed rejects borrow beyond spot CF capacity", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // borrow 801e8 > 800e8 => shortfall + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("801", 8)); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + }); + + // ========================================================================= + // Section L: Asymmetric bounded prices + // ========================================================================= + describe("L. Asymmetric bounded prices", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("L.1 - collateral price below spot reduces borrowing power", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // Lower collateral price => lower collateral value + dbo.getBoundedCollateralPriceView.returns(parseUnits("0.5", 18)); // $0.50 + dbo.getBoundedDebtPriceView.returns(SPOT_PRICE); // $1 (same as spot) + dbo.getBoundedPricesView.returns([parseUnits("0.5", 18), SPOT_PRICE]); + + // sumCollateral = 0.8 * 1 * 0.5 * 1000e8 = 400e8 + const [err, liquidity] = await comptroller.getBorrowingPower(await user.getAddress()); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("400", 8)); + }); + + it("L.2 - debt price above spot increases borrow cost", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + dbo.getBoundedCollateralPriceView.returns(SPOT_PRICE); // $1 + dbo.getBoundedDebtPriceView.returns(parseUnits("2", 18)); // $2 + dbo.getBoundedPricesView.returns([SPOT_PRICE, parseUnits("2", 18)]); + + // sumCollateral = 0.8 * 1 * 1 * 1000e8 = 800e8 + // Borrow 500e8: sumBorrow = 2 * 500e8 = 1000e8 > 800e8 => shortfall + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("500", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const [err, , shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(shortfall).to.equal(parseUnits("200", 8)); // 1000e8 - 800e8 + }); + + it("L.3 - both bounded prices more conservative => strictly tighter position", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Check with spot-like bounded prices first + dbo.getBoundedCollateralPriceView.returns(SPOT_PRICE); + dbo.getBoundedDebtPriceView.returns(SPOT_PRICE); + dbo.getBoundedPricesView.returns([SPOT_PRICE, SPOT_PRICE]); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("500", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const [, liquiditySpot] = await comptroller.getBorrowingPower(userAddr); + + // Now with conservative bounded prices + dbo.getBoundedCollateralPriceView.returns(BOUNDED_COLLATERAL_PRICE); // lower + dbo.getBoundedDebtPriceView.returns(BOUNDED_DEBT_PRICE); // higher + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, BOUNDED_DEBT_PRICE]); + + const [, liquidityBounded] = await comptroller.getBorrowingPower(userAddr); + + expect(liquidityBounded).to.be.lt(liquiditySpot); + }); + }); + + // ========================================================================= + // Section M: Multi-asset scenarios + // ========================================================================= + describe("M. Multi-asset scenarios", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("M.1 - DBO calls are made for each entered asset", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + dbo.getBoundedPricesView.reset(); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, BOUNDED_DEBT_PRICE]); + + await comptroller.getBorrowingPower(await user.getAddress()); + + expect(dbo.getBoundedPricesView).to.have.been.calledWith(vTokenA.address); + expect(dbo.getBoundedPricesView).to.have.been.calledWith(vTokenB.address); + }); + + it("M.2 - updateProtectionState is called for each entered asset on borrow", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + dbo.updateProtectionState.reset(); + vTokenB.totalBorrows.returns(0); + await comptroller + .connect(vTokenB.wallet) + .borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("10", 8)); + + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenA.address); + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenB.address); + }); + + it("M.3 - different bounded prices per asset are respected", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + const userAddr = await user.getAddress(); + + // vTokenA collateral: balance=1000e8, no borrows + // vTokenB: balance=500e8, borrow=200e8 + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot + .whenCalledWith(userAddr) + .returns([0, parseUnits("500", 8), parseUnits("200", 8), EXCHANGE_RATE]); + + // Different prices per asset + dbo.getBoundedCollateralPriceView.whenCalledWith(vTokenA.address).returns(parseUnits("0.8", 18)); + dbo.getBoundedCollateralPriceView.whenCalledWith(vTokenB.address).returns(parseUnits("0.5", 18)); + dbo.getBoundedDebtPriceView.whenCalledWith(vTokenA.address).returns(parseUnits("1.2", 18)); + dbo.getBoundedDebtPriceView.whenCalledWith(vTokenB.address).returns(parseUnits("1.5", 18)); + dbo.getBoundedPricesView.whenCalledWith(vTokenA.address).returns([parseUnits("0.8", 18), parseUnits("1.2", 18)]); + dbo.getBoundedPricesView.whenCalledWith(vTokenB.address).returns([parseUnits("0.5", 18), parseUnits("1.5", 18)]); + + // vTokenA: tokensToDenom = 0.8 * 1 * 0.8 = 0.64 => sumCollateral += 0.64 * 1000e8 = 640e8 + // vTokenB: tokensToDenom = 0.8 * 1 * 0.5 = 0.40 => sumCollateral += 0.40 * 500e8 = 200e8 + // total collateral = 840e8 + // + // vTokenA borrows: debtPrice * 0 = 0 + // vTokenB borrows: debtPrice * 200e8 = 1.5 * 200e8 = 300e8 + // total borrows = 300e8 + // + // liquidity = 840e8 - 300e8 = 540e8 + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("540", 8)); + expect(shortfall).to.equal(0); + }); + }); + + // ========================================================================= + // Section N: Edge cases and error handling + // ========================================================================= + describe("N. Edge cases and error handling", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("N.1 - SNAPSHOT_ERROR propagates correctly", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Return error from getAccountSnapshot + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([1, 0, 0, 0]); + + const [err] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(Error.SNAPSHOT_ERROR); + }); + + it("N.2 - zero vToken balance yields zero collateral", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, 0, EXCHANGE_RATE]); + + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.equal(0); + }); + + it("N.3 - very large bounded prices do not overflow", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // Large price but within reasonable uint256 range + dbo.getBoundedCollateralPriceView.returns(parseUnits("1000000", 18)); + dbo.getBoundedDebtPriceView.returns(parseUnits("1000000", 18)); + dbo.getBoundedPricesView.returns([parseUnits("1000000", 18), parseUnits("1000000", 18)]); + + const [err, liquidity] = await comptroller.getBorrowingPower(await user.getAddress()); + expect(err).to.equal(0); + expect(liquidity).to.be.gt(0); + }); + + it("N.4 - very small bounded collateral price (near zero) results in minimal collateral", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedCollateralPriceView.returns(1); // 1 wei + dbo.getBoundedDebtPriceView.returns(SPOT_PRICE); + dbo.getBoundedPricesView.returns([1, SPOT_PRICE]); + + const [err, liquidity] = await comptroller.getBorrowingPower(await user.getAddress()); + expect(err).to.equal(0); + // CF * ER * 1_wei * 1000e8 / 1e18 ≈ 0 (truncated) + expect(liquidity).to.equal(0); + }); + + it("N.5 - zero exchange rate results in zero collateral", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, 0]); // zero ER + + const [err, liquidity] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + }); + + it("N.6 - oracle returning 0 for spot price causes PRICE_ERROR on borrow", async () => { + const { comptroller, vTokenA, vTokenB, user, oracle, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + oracle.getUnderlyingPrice.whenCalledWith(vTokenB.address).returns(0); + dbo.getBoundedPricesView.whenCalledWith(vTokenB.address).returns([0, 0]); + vTokenB.totalBorrows.returns(0); + + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("10", 8)); + expect(errCode).to.equal(Error.PRICE_ERROR); + }); + + it("N.7 - getAccountLiquidity returns PRICE_ERROR when spot oracle returns 0", async () => { + const { comptroller, vTokenA, user, oracle } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + oracle.getUnderlyingPrice.returns(0); + + const [err] = await comptroller.getAccountLiquidity(await user.getAddress()); + expect(err).to.equal(Error.PRICE_ERROR); + }); + }); + + // ========================================================================= + // Section O: VAI debt interaction + // ========================================================================= + describe("O. VAI debt interaction with bounded prices", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("O.1 - VAI debt is added to sumBorrows in CF path", async () => { + const { comptroller, vTokenA, user, vaiController } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // sumCollateral = 640e8 at bounded + // VAI debt = 640e8 (exactly equal => 0 liquidity) + vaiController.getVAIRepayAmount.whenCalledWith(userAddr).returns(parseUnits("640", 8)); + + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.equal(0); + }); + + it("O.2 - VAI debt exceeding bounded collateral causes shortfall", async () => { + const { comptroller, vTokenA, user, vaiController } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // sumCollateral = 640e8 + // VAI debt = 700e8 => shortfall = 60e8 + vaiController.getVAIRepayAmount.whenCalledWith(userAddr).returns(parseUnits("700", 8)); + + const [err, , shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(shortfall).to.equal(parseUnits("60", 8)); + }); + + it("O.3 - VAI debt is also added in LT path", async () => { + const { comptroller, vTokenA, user, vaiController } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // sumCollateral_LT = 900e8 + // VAI debt = 950e8 => shortfall = 50e8 + vaiController.getVAIRepayAmount.whenCalledWith(userAddr).returns(parseUnits("950", 8)); + + const [err, , shortfall] = await comptroller.getAccountLiquidity(userAddr); + expect(err).to.equal(0); + expect(shortfall).to.equal(parseUnits("50", 8)); + }); + + it("O.4 - VAI + token borrows combined in bounded CF path", async () => { + const { comptroller, vTokenA, vTokenB, user, vaiController } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("200", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // VAI debt = 100e8 + vaiController.getVAIRepayAmount.whenCalledWith(userAddr).returns(parseUnits("100", 8)); + + // sumCollateral = 640e8 + // sumBorrow = 1.2 * 200e8 + 100e8 = 240e8 + 100e8 = 340e8 + // liquidity = 640e8 - 340e8 = 300e8 + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("300", 8)); + expect(shortfall).to.equal(0); + }); + }); + + // ========================================================================= + // Section P: CF vs LT path divergence + // ========================================================================= + describe("P. CF vs LT path divergence", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("P.1 - account can be solvent at LT but in shortfall at bounded CF", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Borrow 700e8 + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("700", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // LT path: sumCollateral = 900e8, sumBorrow = 700e8 => liquidity = 200e8 + const [errLT, liquidityLT, shortfallLT] = await comptroller.getAccountLiquidity(userAddr); + expect(errLT).to.equal(0); + expect(liquidityLT).to.equal(parseUnits("200", 8)); + expect(shortfallLT).to.equal(0); + + // CF path (bounded): sumCollateral = 640e8, sumBorrow = 840e8 => shortfall = 200e8 + const [errCF, liquidityCF, shortfallCF] = await comptroller.getBorrowingPower(userAddr); + expect(errCF).to.equal(0); + expect(liquidityCF).to.equal(0); + expect(shortfallCF).to.equal(parseUnits("200", 8)); + }); + + it("P.2 - liquidation not allowed when solvent at LT even if shortfall at CF", async () => { + const { comptroller, vTokenA, vTokenB, user, liquidator } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Borrow 700e8 => solvent at LT, shortfall at CF + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("700", 8), EXCHANGE_RATE]); + vTokenB.borrowBalanceStored.whenCalledWith(userAddr).returns(parseUnits("700", 8)); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const errCode = await comptroller.callStatic.liquidateBorrowAllowed( + vTokenB.address, + vTokenA.address, + await liquidator.getAddress(), + userAddr, + parseUnits("100", 8), + ); + expect(errCode).to.equal(Error.INSUFFICIENT_SHORTFALL); + }); + + it("P.3 - borrow blocked by CF bounded path even though LT shows liquidity", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Existing borrow of 500e8 + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("500", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // Additional borrow of 100e8: at bounded, total borrow effect = 1.2 * (500+100)e8 = 720e8 > 640e8 + vTokenB.totalBorrows.returns(parseUnits("500", 8)); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, userAddr, parseUnits("100", 8)); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + + it("P.4 - redeem blocked by CF bounded path even though LT shows sufficient collateral", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Borrow 500e8 + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("500", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // At bounded: sumCollateral=640e8, sumBorrow=600e8. Redeem 100 adds 64e8 => 664e8 > 640e8 + // At LT: sumCollateral=900e8, sumBorrow=500e8. Redeem 100 adds 90e8 => 590e8 < 900e8 (OK at LT) + const errCode = await comptroller.callStatic.redeemAllowed(vTokenA.address, userAddr, parseUnits("100", 8)); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + }); + + // ========================================================================= + // Section Q: enterPool (CF path, state-changing) + // ========================================================================= + describe("Q. enterPool (CF path)", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("Q.1 - enterPool calls _updateProtectionStates via _getAccountLiquidity", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // Create a pool + await comptroller.createPool("test-pool"); + const poolId = await comptroller.lastPoolId(); + await comptroller.addPoolMarkets([poolId], [vTokenA.address]); + + dbo.updateProtectionState.reset(); + + // enterPool triggers _getAccountLiquidity with CF weighting + await comptroller.connect(user).enterPool(poolId); + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenA.address); + }); + + it("Q.2 - enterPool reverts if bounded-price liquidity check fails", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Enter B with borrows + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("700", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // At bounded: shortfall exists (640e8 < 840e8) + await comptroller.createPool("test-pool-2"); + const poolId = await comptroller.lastPoolId(); + await comptroller.addPoolMarkets([poolId], [vTokenA.address]); + await comptroller.addPoolMarkets([poolId], [vTokenB.address]); + await comptroller.setIsBorrowAllowed(poolId, vTokenB.address, true); + + await expect(comptroller.connect(user).enterPool(poolId)).to.be.revertedWithCustomError( + comptroller, + "LiquidityCheckFailed", + ); + }); + }); + + // ========================================================================= + // Section R: DBO reconfiguration + // ========================================================================= + describe("R. DBO reconfiguration", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("R.1 - changing DBO address affects subsequent liquidity checks", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Current bounded: liquidity = 640e8 + const [, liquidity1] = await comptroller.getBorrowingPower(userAddr); + expect(liquidity1).to.equal(parseUnits("640", 8)); + + // Deploy a new DBO with different prices + const dbo2 = await smock.fake("IDeviationBoundedOracle"); + dbo2.getBoundedCollateralPriceView.returns(parseUnits("0.5", 18)); // $0.50 + dbo2.getBoundedDebtPriceView.returns(parseUnits("1.5", 18)); // $1.50 + dbo2.getBoundedPricesView.returns([parseUnits("0.5", 18), parseUnits("1.5", 18)]); + await comptroller.setDeviationBoundedOracle(dbo2.address); + + // New liquidity = 0.8 * 1 * 0.5 * 1000e8 = 400e8 + const [, liquidity2] = await comptroller.getBorrowingPower(userAddr); + expect(liquidity2).to.equal(parseUnits("400", 8)); + }); + + it("R.2 - swapping DBO to a different instance works", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Replace with a new DBO that returns different prices + const newDbo = await smock.fake("IDeviationBoundedOracle"); + newDbo.getBoundedCollateralPriceView.returns(parseUnits("0.5", 18)); + newDbo.getBoundedDebtPriceView.returns(parseUnits("1.5", 18)); + newDbo.getBoundedPricesView.returns([parseUnits("0.5", 18), parseUnits("1.5", 18)]); + await comptroller.setDeviationBoundedOracle(newDbo.address); + expect(await comptroller.deviationBoundedOracle()).to.equal(newDbo.address); + + // sumCollateral = 0.8 * 1 * 0.5 * 1000e8 = 400e8 + const [err, liquidity] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("400", 8)); + }); + + it("R.3 - changing bounded prices on existing DBO takes effect immediately", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + const [, liquidity1] = await comptroller.getBorrowingPower(userAddr); + expect(liquidity1).to.equal(parseUnits("640", 8)); + + // Change DBO return values + dbo.getBoundedCollateralPriceView.returns(parseUnits("0.6", 18)); + dbo.getBoundedPricesView.returns([parseUnits("0.6", 18), BOUNDED_DEBT_PRICE]); + // sumCollateral = 0.8 * 1 * 0.6 * 1000e8 = 480e8 + const [, liquidity2] = await comptroller.getBorrowingPower(userAddr); + expect(liquidity2).to.equal(parseUnits("480", 8)); + }); + }); + + // ========================================================================= + // Section S: Consistency and regression tests + // ========================================================================= + describe("S. Consistency and regression tests", () => { + let fixture: DboFixture; + + beforeEach(async () => { + fixture = await loadFixture(deployDboFixture); + configureFakes(fixture); + }); + + it("S.1 - getBorrowingPower and getHypotheticalAccountLiquidity(0,0) return same values", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("300", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const bp = await comptroller.getBorrowingPower(userAddr); + const hl = await comptroller.getHypotheticalAccountLiquidity(userAddr, ethers.constants.AddressZero, 0, 0); + + expect(bp[0]).to.equal(hl[0]); + expect(bp[1]).to.equal(hl[1]); + expect(bp[2]).to.equal(hl[2]); + }); + + it("S.2 - hypothetical borrow of 0 returns same as no-modification call", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + const noMod = await comptroller.getHypotheticalAccountLiquidity(userAddr, ethers.constants.AddressZero, 0, 0); + const zeroBorrow = await comptroller.getHypotheticalAccountLiquidity(userAddr, vTokenB.address, 0, 0); + + expect(noMod[0]).to.equal(zeroBorrow[0]); + expect(noMod[1]).to.equal(zeroBorrow[1]); + expect(noMod[2]).to.equal(zeroBorrow[2]); + }); + + it("S.3 - increasing borrow amount monotonically decreases liquidity", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + const userAddr = await user.getAddress(); + + const [, liq100] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenB.address, + 0, + parseUnits("100", 8), + ); + const [, liq200] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenB.address, + 0, + parseUnits("200", 8), + ); + const [, liq300] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenB.address, + 0, + parseUnits("300", 8), + ); + + expect(liq100).to.be.gt(liq200); + expect(liq200).to.be.gt(liq300); + }); + + it("S.4 - increasing redeem amount monotonically decreases liquidity", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + const [, liq100] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenA.address, + parseUnits("100", 8), + 0, + ); + const [, liq200] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenA.address, + parseUnits("200", 8), + 0, + ); + const [, liq500] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenA.address, + parseUnits("500", 8), + 0, + ); + + expect(liq100).to.be.gt(liq200); + expect(liq200).to.be.gt(liq500); + }); + + it("S.5 - lowering bounded collateral price reduces borrowing power", async () => { + const { comptroller, vTokenA, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + dbo.getBoundedCollateralPriceView.returns(parseUnits("0.9", 18)); + dbo.getBoundedPricesView.returns([parseUnits("0.9", 18), BOUNDED_DEBT_PRICE]); + const [, liq1] = await comptroller.getBorrowingPower(userAddr); + + dbo.getBoundedCollateralPriceView.returns(parseUnits("0.7", 18)); + dbo.getBoundedPricesView.returns([parseUnits("0.7", 18), BOUNDED_DEBT_PRICE]); + const [, liq2] = await comptroller.getBorrowingPower(userAddr); + + expect(liq1).to.be.gt(liq2); + }); + + it("S.6 - raising bounded debt price reduces liquidity", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("300", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + dbo.getBoundedDebtPriceView.returns(parseUnits("1.0", 18)); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, parseUnits("1.0", 18)]); + const [, liq1] = await comptroller.getBorrowingPower(userAddr); + + dbo.getBoundedDebtPriceView.returns(parseUnits("1.5", 18)); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, parseUnits("1.5", 18)]); + const [, liq2, shortfall2] = await comptroller.getBorrowingPower(userAddr); + + // liq1 should be higher (or liq2 should be lower / have shortfall) + if (shortfall2.gt(0)) { + expect(liq1).to.be.gt(0); + } else { + expect(liq1).to.be.gt(liq2); + } + }); + + it("S.7 - redeemAllowed and transferAllowed behave identically for same tokens", async () => { + const { comptroller, vTokenA, vTokenB, user, root } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("400", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + const redeemResult = await comptroller.callStatic.redeemAllowed(vTokenA.address, userAddr, parseUnits("50", 8)); + const transferResult = await comptroller.callStatic.transferAllowed( + vTokenA.address, + userAddr, + await root.getAddress(), + parseUnits("50", 8), + ); + + expect(redeemResult).to.equal(transferResult); + }); + + it("S.8 - multiple sequential borrows each update protection state", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + vTokenB.totalBorrows.returns(0); + + // First borrow + dbo.updateProtectionState.reset(); + await comptroller + .connect(vTokenB.wallet) + .borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("10", 8)); + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenA.address); + + // Second borrow — reset and verify it's called again + dbo.updateProtectionState.reset(); + await comptroller + .connect(vTokenB.wallet) + .borrowAllowed(vTokenB.address, await user.getAddress(), parseUnits("10", 8)); + expect(dbo.updateProtectionState).to.have.been.calledWith(vTokenA.address); + }); + + it("S.9 - exact boundary: borrow that exactly equals bounded capacity", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + // Make debt price exactly $1 so borrow amount = sumCollateral + dbo.getBoundedDebtPriceView.returns(SPOT_PRICE); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, SPOT_PRICE]); + // sumCollateral = 0.8 * 1 * 0.8 * 1000e8 = 640e8 + // borrow exactly 640e8 at debt price $1 => sumBorrow = 640e8 = sumCollateral => no shortfall + const borrowAmount = parseUnits("640", 8); + vTokenB.totalBorrows.returns(0); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(errCode).to.equal(Error.NO_ERROR); + }); + + it("S.10 - exact boundary: borrow 1 wei over bounded capacity fails", async () => { + const { comptroller, vTokenA, vTokenB, user, dbo } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + + dbo.getBoundedDebtPriceView.returns(SPOT_PRICE); + dbo.getBoundedPricesView.returns([BOUNDED_COLLATERAL_PRICE, SPOT_PRICE]); + // borrow 641e8 at debt price $1 => sumBorrow = 641e8 > 640e8 => shortfall + const borrowAmount = parseUnits("641", 8); + vTokenB.totalBorrows.returns(0); + const errCode = await comptroller + .connect(vTokenB.wallet) + .callStatic.borrowAllowed(vTokenB.address, await user.getAddress(), borrowAmount); + expect(errCode).to.equal(Error.INSUFFICIENT_LIQUIDITY); + }); + + it("S.11 - CF path divergence: verify exact bounded liquidity math", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Borrow 300e8 on B + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("300", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // sumCollateral = 0.8 * 1 * 0.8 * 1000e8 = 640e8 + // sumBorrow = 1.2 * 300e8 = 360e8 + // liquidity = 640e8 - 360e8 = 280e8 + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("280", 8)); + expect(shortfall).to.equal(0); + }); + + it("S.12 - LT path: verify exact spot liquidity math", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + vTokenA.getAccountSnapshot.whenCalledWith(userAddr).returns([0, COLLATERAL_BALANCE, 0, EXCHANGE_RATE]); + vTokenB.getAccountSnapshot.whenCalledWith(userAddr).returns([0, 0, parseUnits("300", 8), EXCHANGE_RATE]); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + + // sumCollateral_LT = 0.9 * 1 * 1 * 1000e8 = 900e8 + // sumBorrow = 1 * 300e8 = 300e8 + // liquidity = 900e8 - 300e8 = 600e8 + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(userAddr); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("600", 8)); + expect(shortfall).to.equal(0); + }); + + it("S.13 - hypothetical borrow at bounded: exact shortfall calculation", async () => { + const { comptroller, vTokenA, vTokenB, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + await comptroller.connect(user).enterMarkets([vTokenB.address]); + const userAddr = await user.getAddress(); + + // Hypothetical borrow 600e8 on B + // sumCollateral = 640e8 + // hypothetical sumBorrow = 1.2 * 600e8 = 720e8 + // shortfall = 720e8 - 640e8 = 80e8 + const [err, liquidity, shortfall] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenB.address, + 0, + parseUnits("600", 8), + ); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.equal(parseUnits("80", 8)); + }); + + it("S.14 - hypothetical redeem at bounded: exact liquidity calculation", async () => { + const { comptroller, vTokenA, user } = fixture; + await enterCollateralMarket(comptroller, vTokenA, user); + const userAddr = await user.getAddress(); + + // Hypothetical redeem 200 vTokens from A + // sumCollateral = 640e8 + // hypothetical adds tokensToDenom * 200e8 = 0.64 * 200e8 = 128e8 to borrows + // liquidity = 640e8 - 128e8 = 512e8 + const [err, liquidity, shortfall] = await comptroller.getHypotheticalAccountLiquidity( + userAddr, + vTokenA.address, + parseUnits("200", 8), + 0, + ); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("512", 8)); + expect(shortfall).to.equal(0); + }); + + it("S.15 - CF and LT paths both handle zero-collateral zero-borrow correctly", async () => { + const { comptroller, user } = fixture; + const userAddr = await user.getAddress(); + + const bp = await comptroller.getBorrowingPower(userAddr); + const al = await comptroller.getAccountLiquidity(userAddr); + + expect(bp[0]).to.equal(0); + expect(bp[1]).to.equal(0); + expect(bp[2]).to.equal(0); + expect(al[0]).to.equal(0); + expect(al[1]).to.equal(0); + expect(al[2]).to.equal(0); + }); + }); +}); diff --git a/tests/hardhat/Comptroller/Diamond/flashLoan.ts b/tests/hardhat/Comptroller/Diamond/flashLoan.ts index 634f92fa2..0b9f1bc34 100644 --- a/tests/hardhat/Comptroller/Diamond/flashLoan.ts +++ b/tests/hardhat/Comptroller/Diamond/flashLoan.ts @@ -13,6 +13,7 @@ import { ComptrollerLens__factory, ComptrollerMock, IAccessControlManagerV5, + IDeviationBoundedOracle, IProtocolShareReserve, InterestRateModel, MockFlashLoanReceiver, @@ -68,6 +69,10 @@ const flashLoanTestFixture = async (): Promise => { await comptroller._setComptrollerLens(comptrollerLens.address); await comptroller._setPriceOracle(oracle.address); + const dbo = await smock.fake("IDeviationBoundedOracle"); + dbo.getBoundedPricesView.returns([convertToUnit(1, 18), convertToUnit(1, 18)]); + await comptroller.setDeviationBoundedOracle(dbo.address); + return { admin, oracle, diff --git a/tests/hardhat/Comptroller/Diamond/oraclePumpCrashTest.ts b/tests/hardhat/Comptroller/Diamond/oraclePumpCrashTest.ts new file mode 100644 index 000000000..9f3c4cb53 --- /dev/null +++ b/tests/hardhat/Comptroller/Diamond/oraclePumpCrashTest.ts @@ -0,0 +1,1342 @@ +import { FakeContract, MockContract, smock } from "@defi-wonderland/smock"; +import { loadFixture } from "@nomicfoundation/hardhat-network-helpers"; +import chai from "chai"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; +import { SignerWithAddress } from "hardhat-deploy-ethers/signers"; + +import { + ComptrollerLens, + ComptrollerLens__factory, + ComptrollerMock, + IAccessControlManagerV5, + IDeviationBoundedOracle, + IProtocolShareReserve, + InterestRateModel, + MockToken, + MockToken__factory, + PriceOracle, + Unitroller, + VBep20Delegator__factory, +} from "../../../../typechain"; +import { deployDiamond } from "./scripts/deploy"; + +const { expect } = chai; +chai.use(smock.matchers); + +// --------------------------------------------------------------------------- +// Constants +// --------------------------------------------------------------------------- +const NORMAL_PRICE = parseUnits("100", 18); // $100 per token +const CF = parseUnits("0.8", 18); // 80% +const LT = parseUnits("0.9", 18); // 90% +const CLOSE_FACTOR = parseUnits("0.5", 18); +const LIQUIDATION_INCENTIVE = parseUnits("1.1", 18); +const SUPPLY_CAP = parseUnits("10000000", 18); +const BORROW_CAP = parseUnits("5000000", 18); +const INITIAL_EXCHANGE_RATE = parseUnits("1", 18); // 1:1 for clean math +const COLLATERAL_AMOUNT = parseUnits("1000", 18); // 1000 underlying → 1000 vTokens at ER=1 +const POOL_LIQUIDITY = parseUnits("100000", 18); // plenty of liquidity in borrow pool + +/* + * Math reference (at ER=1, 18 decimals): + * + * tokensToDenom = weightedFactor × exchangeRate × collateralPrice / 1e18 / 1e18 + * sumCollateral = tokensToDenom × vTokenBalance / 1e18 + * sumBorrow = debtPrice × borrowBalance / 1e18 + * + * At NORMAL ($100), CF=0.8, ER=1, vTokenBalance=1000e18: + * tokensToDenom = 0.8e18 × 1e18 × 100e18 / 1e18 / 1e18 = 80e18 + * sumCollateral = 80e18 × 1000e18 / 1e18 = 80000e18 + * maxBorrow at $100/token debt = 800e18 underlying + * + * At LT=0.9: + * sumCollateral = 90e18 × 1000e18 / 1e18 = 90000e18 + * maxBorrow at $100/token debt = 900e18 underlying + */ + +// --------------------------------------------------------------------------- +// Fixture type +// --------------------------------------------------------------------------- +type RealVTokenFixture = { + admin: SignerWithAddress; + user: SignerWithAddress; + attacker: SignerWithAddress; + liquidator: SignerWithAddress; + comptroller: ComptrollerMock; + unitroller: Unitroller; + comptrollerLens: MockContract; + oracle: FakeContract; + dbo: FakeContract; + accessControl: FakeContract; + interestRateModel: FakeContract; + protocolShareReserve: FakeContract; + vTokenA: any; // collateral market (VBep20MockDelegate) + vTokenB: any; // borrow market (VBep20MockDelegate) + underlyingA: MockContract; + underlyingB: MockContract; +}; + +// --------------------------------------------------------------------------- +// Fixture deploy +// --------------------------------------------------------------------------- +async function deployRealVTokenFixture(): Promise { + const [admin, user, attacker, liquidator] = await ethers.getSigners(); + + // 1. Deploy diamond comptroller + const result = await deployDiamond(""); + const unitroller = result.unitroller; + const comptroller = await ethers.getContractAt("ComptrollerMock", unitroller.address); + + // 2. Fakes: ACL, Oracle, DBO, InterestRateModel, ProtocolShareReserve + const accessControl = await smock.fake("IAccessControlManagerV5"); + accessControl.isAllowedToCall.returns(true); + + const oracle = await smock.fake("contracts/Oracle/PriceOracle.sol:PriceOracle"); + oracle.getUnderlyingPrice.returns(NORMAL_PRICE); + + const dbo = await smock.fake("IDeviationBoundedOracle"); + dbo.getBoundedPricesView.returns([NORMAL_PRICE, NORMAL_PRICE]); + + const interestRateModel = await smock.fake("InterestRateModel"); + interestRateModel.isInterestRateModel.returns(true); + interestRateModel.getBorrowRate.returns(0); + interestRateModel.getSupplyRate.returns(0); + + const protocolShareReserve = await smock.fake( + "contracts/external/IProtocolShareReserve.sol:IProtocolShareReserve", + ); + + // 3. Real ComptrollerLens + const LensFactory = await smock.mock("ComptrollerLens"); + const comptrollerLens = await LensFactory.deploy(); + + // 4. Configure comptroller + await comptroller._setAccessControl(accessControl.address); + await comptroller._setComptrollerLens(comptrollerLens.address); + await comptroller._setPriceOracle(oracle.address); + await comptroller.setDeviationBoundedOracle(dbo.address); + await comptroller._setCloseFactor(CLOSE_FACTOR); + + // 5. Deploy real underlying tokens + const underlyingFactory = await smock.mock("MockToken"); + const underlyingA = await underlyingFactory.deploy("Token A", "TKNA", 18); + const underlyingB = await underlyingFactory.deploy("Token B", "TKNB", 18); + + // 6. Deploy real vTokens (delegator + delegate pattern, like flashLoan.ts) + const VBep20ImplFactory = await ethers.getContractFactory("VBep20MockDelegate"); + const vTokenImpl = await VBep20ImplFactory.deploy(); + await vTokenImpl.deployed(); + + const vTokenAProxy = await new VBep20Delegator__factory(admin).deploy( + underlyingA.address, + comptroller.address, + interestRateModel.address, + INITIAL_EXCHANGE_RATE, + "vToken A", + "vTKNA", + 18, + admin.address, + vTokenImpl.address, + "0x", + ); + const vTokenA = await ethers.getContractAt("VBep20MockDelegate", vTokenAProxy.address); + + const vTokenBProxy = await new VBep20Delegator__factory(admin).deploy( + underlyingB.address, + comptroller.address, + interestRateModel.address, + INITIAL_EXCHANGE_RATE, + "vToken B", + "vTKNB", + 18, + admin.address, + vTokenImpl.address, + "0x", + ); + const vTokenB = await ethers.getContractAt("VBep20MockDelegate", vTokenBProxy.address); + + // 7. Configure vTokens + await vTokenA.setAccessControlManager(accessControl.address); + await vTokenA.setProtocolShareReserve(protocolShareReserve.address); + await vTokenB.setAccessControlManager(accessControl.address); + await vTokenB.setProtocolShareReserve(protocolShareReserve.address); + + // 8. Support markets and configure + await comptroller._supportMarket(vTokenA.address); + await comptroller._supportMarket(vTokenB.address); + await comptroller["setCollateralFactor(address,uint256,uint256)"](vTokenA.address, CF, LT); + await comptroller["setCollateralFactor(address,uint256,uint256)"](vTokenB.address, CF, LT); + await comptroller.setMarketSupplyCaps([vTokenA.address, vTokenB.address], [SUPPLY_CAP, SUPPLY_CAP]); + await comptroller.setMarketBorrowCaps([vTokenA.address, vTokenB.address], [BORROW_CAP, BORROW_CAP]); + await comptroller.setIsBorrowAllowed(0, vTokenA.address, true); + await comptroller.setIsBorrowAllowed(0, vTokenB.address, true); + await comptroller["setLiquidationIncentive(address,uint256)"](vTokenA.address, LIQUIDATION_INCENTIVE); + await comptroller["setLiquidationIncentive(address,uint256)"](vTokenB.address, LIQUIDATION_INCENTIVE); + + // Pre-fund vTokenB pool with liquidity for borrows (contract can't call faucet) + await underlyingB.setVariable("_balances", { [vTokenB.address]: POOL_LIQUIDITY }); + await underlyingB.setVariable("_totalSupply", POOL_LIQUIDITY); + await vTokenB.harnessSetInternalCash(POOL_LIQUIDITY); + + return { + admin, + user, + attacker, + liquidator, + comptroller, + unitroller, + comptrollerLens, + oracle, + dbo, + accessControl, + interestRateModel, + protocolShareReserve, + vTokenA, + vTokenB, + underlyingA, + underlyingB, + }; +} + +// --------------------------------------------------------------------------- +// Helper: set up a user with collateral in vTokenA and optional borrow from vTokenB +// --------------------------------------------------------------------------- +async function setupPosition( + fixture: RealVTokenFixture, + signer: SignerWithAddress, + collateralAmount: ReturnType, + borrowAmount?: ReturnType, +): Promise { + const { comptroller, vTokenA, vTokenB, underlyingA } = fixture; + + // Supply collateral in vTokenA + await underlyingA.connect(signer).faucet(collateralAmount); + await underlyingA.connect(signer).approve(vTokenA.address, collateralAmount); + await vTokenA.connect(signer).mint(collateralAmount); + await comptroller.connect(signer).enterMarkets([vTokenA.address]); + + // Pool is pre-funded in fixture; just borrow if requested + if (borrowAmount && borrowAmount.gt(0)) { + await vTokenB.connect(signer).borrow(borrowAmount); + } +} + +// --------------------------------------------------------------------------- +// Reset smock fakes to default values (smock state is JS-side, not EVM-restored) +// --------------------------------------------------------------------------- +function resetFakes(f: RealVTokenFixture): void { + // Oracle + f.oracle.getUnderlyingPrice.reset(); + f.oracle.getUnderlyingPrice.returns(NORMAL_PRICE); + + // DBO + f.dbo.updateProtectionState.reset(); + f.dbo.getBoundedPricesView.reset(); + f.dbo.getBoundedPricesView.returns([NORMAL_PRICE, NORMAL_PRICE]); + + // ACL + f.accessControl.isAllowedToCall.reset(); + f.accessControl.isAllowedToCall.returns(true); + + // InterestRateModel + f.interestRateModel.isInterestRateModel.reset(); + f.interestRateModel.isInterestRateModel.returns(true); + f.interestRateModel.getBorrowRate.reset(); + f.interestRateModel.getBorrowRate.returns(0); + f.interestRateModel.getSupplyRate.reset(); + f.interestRateModel.getSupplyRate.returns(0); +} + +// =========================================================================== +// Tests +// =========================================================================== +describe("Oracle Pump/Crash — vToken Integration Tests", () => { + // ========================================================================= + // Part 1.1: Normal Operation (no protection active) + // ========================================================================= + describe("1. Normal Operation (DBO returns spot prices)", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + }); + + it("mint succeeds", async () => { + await f.underlyingA.connect(f.user).faucet(COLLATERAL_AMOUNT); + await f.underlyingA.connect(f.user).approve(f.vTokenA.address, COLLATERAL_AMOUNT); + await expect(f.vTokenA.connect(f.user).mint(COLLATERAL_AMOUNT)).to.not.be.reverted; + + const vBalance = await f.vTokenA.balanceOf(f.user.address); + expect(vBalance).to.be.equal(COLLATERAL_AMOUNT); + }); + + it("borrow succeeds with sufficient collateral", async () => { + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + + // maxBorrow = 800e18 at $100; borrow 700e18 → solvent + const borrowAmount = parseUnits("700", 18); + const uBalBefore = await f.underlyingB.balanceOf(f.user.address); + const borrowBefore = await f.vTokenB.borrowBalanceStored(f.user.address); + await expect(f.vTokenB.connect(f.user).borrow(borrowAmount)).to.emit(f.vTokenB, "Borrow"); + + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore.add(borrowAmount)); + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowBefore.add(borrowAmount)); + }); + + it("redeem succeeds when account stays solvent", async () => { + const borrowAmount = parseUnits("300", 18); + await setupPosition(f, f.user, COLLATERAL_AMOUNT, borrowAmount); + + // Redeem 100 underlying → 900 vTokens remaining + // sumCollateral = 0.8 × 100 × 900 = 72000e18 > sumBorrow = 100 × 300 = 30000e18 + const redeemAmount = parseUnits("100", 18); + const vBalBefore = await f.vTokenA.balanceOf(f.user.address); + const uBalBefore = await f.underlyingA.balanceOf(f.user.address); + await expect(f.vTokenA.connect(f.user).redeemUnderlying(redeemAmount)).to.emit(f.vTokenA, "Redeem"); + + // ER=1 → vTokens burned = underlying redeemed + expect(await f.vTokenA.balanceOf(f.user.address)).to.equal(vBalBefore.sub(redeemAmount)); + expect(await f.underlyingA.balanceOf(f.user.address)).to.equal(uBalBefore.add(redeemAmount)); + }); + + it("repayBorrow succeeds", async () => { + const borrowAmount = parseUnits("300", 18); + await setupPosition(f, f.user, COLLATERAL_AMOUNT, borrowAmount); + + const repayAmount = parseUnits("100", 18); + await f.underlyingB.connect(f.user).faucet(repayAmount); + await f.underlyingB.connect(f.user).approve(f.vTokenB.address, repayAmount); + + const borrowBefore = await f.vTokenB.borrowBalanceStored(f.user.address); + const uBalBefore = await f.underlyingB.balanceOf(f.user.address); + await expect(f.vTokenB.connect(f.user).repayBorrow(repayAmount)).to.emit(f.vTokenB, "RepayBorrow"); + + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowBefore.sub(repayAmount)); + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore.sub(repayAmount)); + }); + + it("transfer succeeds when sender stays solvent", async () => { + const borrowAmount = parseUnits("300", 18); + await setupPosition(f, f.user, COLLATERAL_AMOUNT, borrowAmount); + + // Transfer 100 vTokenA → 900 remaining → still solvent at normal prices + const transferAmount = parseUnits("100", 18); + const srcBefore = await f.vTokenA.balanceOf(f.user.address); + const dstBefore = await f.vTokenA.balanceOf(f.attacker.address); + await expect(f.vTokenA.connect(f.user).transfer(f.attacker.address, transferAmount)).to.emit( + f.vTokenA, + "Transfer", + ); + + expect(await f.vTokenA.balanceOf(f.user.address)).to.equal(srcBefore.sub(transferAmount)); + expect(await f.vTokenA.balanceOf(f.attacker.address)).to.equal(dstBefore.add(transferAmount)); + }); + + it("full lifecycle: mint → enter → borrow → repay → redeem", async () => { + // Mint collateral + await f.underlyingA.connect(f.user).faucet(COLLATERAL_AMOUNT); + await f.underlyingA.connect(f.user).approve(f.vTokenA.address, COLLATERAL_AMOUNT); + await f.vTokenA.connect(f.user).mint(COLLATERAL_AMOUNT); + await f.comptroller.connect(f.user).enterMarkets([f.vTokenA.address]); + + // Verify post-mint: user has vTokens (ER=1) + expect(await f.vTokenA.balanceOf(f.user.address)).to.equal(COLLATERAL_AMOUNT); + + // Fund pool and borrow + await f.underlyingB.setVariable("_balances", { [f.vTokenB.address]: POOL_LIQUIDITY }); + await f.vTokenB.harnessSetInternalCash(POOL_LIQUIDITY); + const borrowAmount = parseUnits("500", 18); + await f.vTokenB.connect(f.user).borrow(borrowAmount); + + // Verify post-borrow: user received underlying, debt recorded + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(borrowAmount); + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowAmount); + + // Repay full borrow + const debt = await f.vTokenB.borrowBalanceStored(f.user.address); + await f.underlyingB.connect(f.user).faucet(debt); + await f.underlyingB.connect(f.user).approve(f.vTokenB.address, debt); + await f.vTokenB.connect(f.user).repayBorrow(debt); + + // Verify post-repay: debt cleared + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(0); + + // Redeem all collateral (no borrows → no shortfall) + const vBalance = await f.vTokenA.balanceOf(f.user.address); + await expect(f.vTokenA.connect(f.user).redeem(vBalance)).to.emit(f.vTokenA, "Redeem"); + + // Verify post-redeem: no vTokens remaining, underlying returned + expect(await f.vTokenA.balanceOf(f.user.address)).to.equal(0); + expect(await f.underlyingA.balanceOf(f.user.address)).to.equal(COLLATERAL_AMOUNT); + }); + }); + + // ========================================================================= + // Part 1.2: Oracle Pump — Collateral Price Inflated ($100 → $500) + // ========================================================================= + describe("2. Oracle Pump — Collateral Price Inflated ($100 → $500)", () => { + /* + * Spot pumps from $100 to $500 for vTokenA. + * DBO clamps collateral at $100 (window minimum). + * + * At bounded ($100), CF=0.8: + * sumCollateral = 0.8 × 1 × 100 × 1000 = 80000e18 + * maxBorrow at $100 debt = 800e18 + */ + const PUMPED_SPOT = parseUnits("500", 18); + + let f: RealVTokenFixture; + + // Helper: apply pump prices to oracle and DBO + function applyPumpPrices(): void { + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(PUMPED_SPOT); + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenB.address).returns(NORMAL_PRICE); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + } + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + + // Set up collateral at NORMAL prices (no borrow yet) + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + }); + + it("mint still works during pump — no liquidity check", async () => { + applyPumpPrices(); + const mintAmount = parseUnits("1000", 18); + await f.underlyingA.connect(f.attacker).faucet(mintAmount); + await f.underlyingA.connect(f.attacker).approve(f.vTokenA.address, mintAmount); + + const vBalBefore = await f.vTokenA.balanceOf(f.attacker.address); + const uBalBefore = await f.underlyingA.balanceOf(f.attacker.address); + await expect(f.vTokenA.connect(f.attacker).mint(mintAmount)).to.emit(f.vTokenA, "Mint"); + + expect(await f.vTokenA.balanceOf(f.attacker.address)).to.equal(vBalBefore.add(mintAmount)); + expect(await f.underlyingA.balanceOf(f.attacker.address)).to.equal(uBalBefore.sub(mintAmount)); + }); + + it("borrow reverts — DBO caps collateral at $100 window min", async () => { + applyPumpPrices(); + // At bounded $100: maxBorrow = 800e18; try 1500e18 → shortfall + const excessBorrow = parseUnits("1500", 18); + await expect(f.vTokenB.connect(f.user).borrow(excessBorrow)).to.be.revertedWith("math error"); + }); + + it("borrow succeeds within bounded capacity despite pump", async () => { + applyPumpPrices(); + // Borrow 700e18 at $100 debt = 70000e18 < 80000e18 sumCollateral + const safeBorrow = parseUnits("700", 18); + const uBalBefore = await f.underlyingB.balanceOf(f.user.address); + const borrowBefore = await f.vTokenB.borrowBalanceStored(f.user.address); + await expect(f.vTokenB.connect(f.user).borrow(safeBorrow)).to.emit(f.vTokenB, "Borrow"); + + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore.add(safeBorrow)); + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowBefore.add(safeBorrow)); + }); + + it("redeem reverts — bounded prices limit withdrawal", async () => { + // Borrow at NORMAL prices first, then pump + await f.vTokenB.connect(f.user).borrow(parseUnits("750", 18)); + applyPumpPrices(); + + // Redeem 200 → 800 remaining: sumCollateral = 0.8 × 100 × 800 = 64000e18 + // sumBorrow = 100 × 750 = 75000e18 → shortfall + await expect(f.vTokenA.connect(f.user).redeemUnderlying(parseUnits("200", 18))).to.be.revertedWith("math error"); + }); + + it("repayBorrow succeeds during pump", async () => { + // Borrow at NORMAL prices first, then pump + await f.vTokenB.connect(f.user).borrow(parseUnits("500", 18)); + applyPumpPrices(); + + const repayAmount = parseUnits("100", 18); + await f.underlyingB.connect(f.user).faucet(repayAmount); + await f.underlyingB.connect(f.user).approve(f.vTokenB.address, repayAmount); + + const borrowBefore = await f.vTokenB.borrowBalanceStored(f.user.address); + const uBalBefore = await f.underlyingB.balanceOf(f.user.address); + await expect(f.vTokenB.connect(f.user).repayBorrow(repayAmount)).to.emit(f.vTokenB, "RepayBorrow"); + + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowBefore.sub(repayAmount)); + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore.sub(repayAmount)); + }); + + it("transfer blocked when bounded prices show shortfall for sender", async () => { + // Borrow at NORMAL prices first, then pump + await f.vTokenB.connect(f.user).borrow(parseUnits("750", 18)); + applyPumpPrices(); + + // Transfer 200 vTokenA → 800 remaining → shortfall at bounded prices + const transferAmount = parseUnits("200", 18); + await expect(f.vTokenA.connect(f.user).transfer(f.attacker.address, transferAmount)).to.emit( + f.vTokenA, + "Failure", + ); + }); + + it("liquidation: borrower solvent at pumped spot LT → INSUFFICIENT_SHORTFALL", async () => { + // Borrow at NORMAL prices first, then pump + await f.vTokenB.connect(f.user).borrow(parseUnits("700", 18)); + applyPumpPrices(); + + // LT path uses spot: sumCollateral = 0.9 × 500 × 1000 = 450000e18 >> sumBorrow = 100 × 700 = 70000e18 + const repayAmount = parseUnits("350", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "Failure"); + }); + + it("getBorrowingPower at bounded $100 unchanged by pump — diverges from LT spot", async () => { + // Before pump: CF path uses DBO [$100,$100], LT path uses spot $100 + const [errBefore, liquidityBefore] = await f.comptroller.getBorrowingPower(f.user.address); + expect(errBefore).to.equal(0); + expect(liquidityBefore).to.equal(parseUnits("80000", 18)); + + // After pump: DBO still returns [$100,$100] → CF path unchanged + applyPumpPrices(); + const [errAfter, liquidityAfter] = await f.comptroller.getBorrowingPower(f.user.address); + expect(errAfter).to.equal(0); + expect(liquidityAfter).to.equal(parseUnits("80000", 18)); + + // LT path sees pumped $500 spot → much higher collateral value + const [ltErr, ltLiquidity] = await f.comptroller.getAccountLiquidity(f.user.address); + expect(ltErr).to.equal(0); + expect(ltLiquidity).to.equal(parseUnits("450000", 18)); + }); + }); + + // ========================================================================= + // Part 1.3: Oracle Crash — Collateral Price Crashed ($100 → $20) + // ========================================================================= + describe("3. Oracle Crash — Collateral Price Crashed ($100 → $20)", () => { + /* + * vTokenA spot crashes from $100 to $20. + * DBO bounds: collateral at $20 (spot = new min), debt at $100 (window max). + * + * At bounded (collateral $20, debt $100), CF=0.8: + * sumCollateral = 0.8 × 20 × 1000 = 16000e18 + * sumBorrow (100e18 borrow) = 100 × 100 = 10000e18 + * + * At spot LT ($20 for vTokenA, $100 for vTokenB): + * sumCollateral = 0.9 × 20 × 1000 = 18000e18 + */ + const CRASHED_SPOT = parseUnits("20", 18); + + let f: RealVTokenFixture; + + // Helper: apply crash prices to oracle and DBO + function applyCrashPrices(): void { + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(CRASHED_SPOT); + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenB.address).returns(NORMAL_PRICE); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([CRASHED_SPOT, CRASHED_SPOT]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + } + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + + // Set up collateral at NORMAL prices (no borrow yet) + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + }); + + it("borrow reverts — crashed collateral + inflated debt", async () => { + applyCrashPrices(); + // sumCollateral = 0.8 × 20 × 1000 = 16000e18 + // Borrow 200e18: sumBorrow = 100 × 200 = 20000e18 > 16000e18 → shortfall + await expect(f.vTokenB.connect(f.user).borrow(parseUnits("200", 18))).to.be.revertedWith("math error"); + }); + + it("redeem reverts — position deeply underwater at bounded prices", async () => { + // Borrow at NORMAL prices first, then crash + await f.vTokenB.connect(f.user).borrow(parseUnits("100", 18)); + applyCrashPrices(); + + // Redeem 500 vTokens → 500 remaining: sumCollateral = 0.8 × 20 × 500 = 8000e18 + // sumBorrow = 100 × 100 = 10000e18 → shortfall + await expect(f.vTokenA.connect(f.user).redeemUnderlying(parseUnits("500", 18))).to.be.revertedWith("math error"); + }); + + it("liquidation: borrower solvent at LT with moderate borrow → INSUFFICIENT_SHORTFALL", async () => { + // Borrow at NORMAL prices first, then crash + await f.vTokenB.connect(f.user).borrow(parseUnits("100", 18)); + applyCrashPrices(); + + // LT: sumCollateral = 0.9 × 20 × 1000 = 18000e18 > sumBorrow = 100 × 100 = 10000e18 → solvent + const repayAmount = parseUnits("50", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "Failure"); // INSUFFICIENT_SHORTFALL + }); + + it("liquidation succeeds when borrower underwater at LT", async () => { + // Borrow at NORMAL prices first, then crash + await f.vTokenB.connect(f.user).borrow(parseUnits("200", 18)); + applyCrashPrices(); + + // LT: sumCollateral = 0.9 × 20 × 1000 = 18000e18 vs sumBorrow = 100 × 200 = 20000e18 + // Shortfall = 2000e18 → liquidation allowed + const repayAmount = parseUnits("100", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + + const liquidatorVTokenBefore = await f.vTokenA.balanceOf(f.liquidator.address); + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "LiquidateBorrow"); + + const liquidatorVTokenAfter = await f.vTokenA.balanceOf(f.liquidator.address); + expect(liquidatorVTokenAfter).to.be.gt(liquidatorVTokenBefore); + }); + + it("getBorrowingPower exact values after crash with 100e18 borrow", async () => { + await f.vTokenB.connect(f.user).borrow(parseUnits("100", 18)); + applyCrashPrices(); + + // CF path: sumCollateral = 0.8 × 20 × 1000 = 16000e18, sumBorrow = 100 × 100 = 10000e18 + const [err, liquidity, shortfall] = await f.comptroller.getBorrowingPower(f.user.address); + expect(err).to.equal(0); + expect(liquidity).to.equal(parseUnits("6000", 18)); + expect(shortfall).to.equal(0); + }); + + it("getBorrowingPower before vs after crash — DBO bounds reduce capacity", async () => { + // Before crash (no borrow): sumCollateral = 0.8 × 100 × 1000 = 80000e18 + const [errBefore, liquidityBefore, shortfallBefore] = await f.comptroller.getBorrowingPower(f.user.address); + expect(errBefore).to.equal(0); + expect(liquidityBefore).to.equal(parseUnits("80000", 18)); + expect(shortfallBefore).to.equal(0); + + // After crash: DBO returns collateral at $20 → sumCollateral = 0.8 × 20 × 1000 = 16000e18 + applyCrashPrices(); + const [errAfter, liquidityAfter, shortfallAfter] = await f.comptroller.getBorrowingPower(f.user.address); + expect(errAfter).to.equal(0); + expect(liquidityAfter).to.equal(parseUnits("16000", 18)); + expect(shortfallAfter).to.equal(0); + + // Capacity dropped by 64000e18 (80% reduction matching 80% price drop from $100 → $20) + expect(liquidityBefore).to.be.gt(liquidityAfter); + expect(liquidityBefore.sub(liquidityAfter)).to.equal(parseUnits("64000", 18)); + }); + }); + + // ========================================================================= + // Part 1.4: Borrow Token Crash — Debt Price Crashed ($100 → $10) + // ========================================================================= + describe("4. Borrow Token Crash — Debt Price Crashed ($100 → $10)", () => { + /* + * vTokenB spot crashes from $100 to $10. DBO bounds debt at $100 (window max). + * Collateral (vTokenA) unchanged at $100. + * + * At bounded: collateral $100, debt $100 (bounded) + * sumCollateral = 0.8 × 100 × 1000 = 80000e18 + * sumBorrow (bounded) = 100 × borrowBalance + * + * At spot $10 debt: + * sumBorrow (spot) = 10 × borrowBalance + */ + const CRASHED_BORROW_SPOT = parseUnits("10", 18); + const BOUNDED_DEBT_AT_MAX = NORMAL_PRICE; // window max $100 + + let f: RealVTokenFixture; + + // Helper: apply borrow token crash prices + function applyBorrowCrashPrices(): void { + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(NORMAL_PRICE); + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenB.address).returns(CRASHED_BORROW_SPOT); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([CRASHED_BORROW_SPOT, BOUNDED_DEBT_AT_MAX]); + } + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + + // Set up collateral at NORMAL prices (no borrow yet) + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + }); + + it("borrow reverts — bounded debt at $100 blocks over-borrowing cheap tokens", async () => { + applyBorrowCrashPrices(); + // At spot $10: 5000 × 10 = 50000e18 < 80000e18 → would succeed + // At bounded $100: 5000 × 100 = 500000e18 >> 80000e18 → blocked + const excessBorrow = parseUnits("5000", 18); + await expect(f.vTokenB.connect(f.user).borrow(excessBorrow)).to.be.revertedWith("math error"); + }); + + it("borrow succeeds within bounded capacity", async () => { + applyBorrowCrashPrices(); + // 700 × 100 = 70000e18 < 80000e18 → OK + const safeBorrow = parseUnits("700", 18); + const uBalBefore = await f.underlyingB.balanceOf(f.user.address); + const borrowBefore = await f.vTokenB.borrowBalanceStored(f.user.address); + await expect(f.vTokenB.connect(f.user).borrow(safeBorrow)).to.emit(f.vTokenB, "Borrow"); + + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore.add(safeBorrow)); + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowBefore.add(safeBorrow)); + }); + + it("liquidation uses spot $10 for debt — borrower very solvent", async () => { + // Borrow at NORMAL prices first, then crash borrow token + await f.vTokenB.connect(f.user).borrow(parseUnits("700", 18)); + applyBorrowCrashPrices(); + + // LT: sumCollateral = 0.9 × 100 × 1000 = 90000e18 + // sumBorrow = 10 × 700 = 7000e18 → very solvent + const repayAmount = parseUnits("350", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "Failure"); // INSUFFICIENT_SHORTFALL + }); + + it("getBorrowingPower unchanged — bounded debt at $100 same as pre-crash", async () => { + await f.vTokenB.connect(f.user).borrow(parseUnits("700", 18)); + + // Before crash: sumCollateral = 0.8 × 100 × 1000 = 80000e18, sumBorrow = 100 × 700 = 70000e18 + const [errBefore, liquidityBefore, shortfallBefore] = await f.comptroller.getBorrowingPower(f.user.address); + expect(errBefore).to.equal(0); + expect(liquidityBefore).to.equal(parseUnits("10000", 18)); + expect(shortfallBefore).to.equal(0); + + // After crash: DBO bounds debt at $100 (window max) → same as before + applyBorrowCrashPrices(); + const [errAfter, liquidityAfter, shortfallAfter] = await f.comptroller.getBorrowingPower(f.user.address); + expect(errAfter).to.equal(0); + expect(liquidityAfter).to.equal(parseUnits("10000", 18)); + expect(shortfallAfter).to.equal(0); + }); + }); + + // ========================================================================= + // Part 1.5: Multi-Step Attack via vToken + // ========================================================================= + describe("5. Multi-Step Attack Scenarios", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + }); + + it("pump-borrow-dump: borrow blocked at pump, safe after dump", async () => { + // Set up position at normal prices + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + + // Step 1: Normal — borrow 700e18 succeeds + const borrow1 = parseUnits("700", 18); + const uBalBefore1 = await f.underlyingB.balanceOf(f.user.address); + await expect(f.vTokenB.connect(f.user).borrow(borrow1)).to.emit(f.vTokenB, "Borrow"); + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore1.add(borrow1)); + + // Repay so we can test pump blocking + const debt = await f.vTokenB.borrowBalanceStored(f.user.address); + await f.underlyingB.connect(f.user).faucet(debt); + await f.underlyingB.connect(f.user).approve(f.vTokenB.address, debt); + await f.vTokenB.connect(f.user).repayBorrow(debt); + + // Step 2: Pump — spot $500, DBO bounds at $100 + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(parseUnits("500", 18)); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + + // Try 2000e18 — at pumped spot would succeed but bounded blocks it + await expect(f.vTokenB.connect(f.user).borrow(parseUnits("2000", 18))).to.be.revertedWith("math error"); + + // Step 3: Dump — prices return to normal + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(NORMAL_PRICE); + + // Borrow 700e18 works again + const borrow3 = parseUnits("700", 18); + const uBalBefore3 = await f.underlyingB.balanceOf(f.user.address); + const borrowBefore3 = await f.vTokenB.borrowBalanceStored(f.user.address); + await expect(f.vTokenB.connect(f.user).borrow(borrow3)).to.emit(f.vTokenB, "Borrow"); + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore3.add(borrow3)); + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowBefore3.add(borrow3)); + }); + + it("borrow at spot → protection activates → redeem blocked", async () => { + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + + // Step 1: DBO returns spot → borrow near max (790e18) + await f.vTokenB.connect(f.user).borrow(parseUnits("790", 18)); + + // Step 2: Protection activates — DBO returns conservative bounded prices + const CONSERVATIVE_COLLATERAL = parseUnits("80", 18); // collateral bounded down + const CONSERVATIVE_DEBT = parseUnits("120", 18); // debt bounded up + f.dbo.getBoundedPricesView + .whenCalledWith(f.vTokenA.address) + .returns([CONSERVATIVE_COLLATERAL, CONSERVATIVE_DEBT]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, CONSERVATIVE_DEBT]); + + // sumCollateral = 0.8 × 80 × 1000 = 64000e18 + // sumBorrow = 120 × 790 = 94800e18 → shortfall = 30800e18 + // Any redeem should fail + await expect(f.vTokenA.connect(f.user).redeemUnderlying(parseUnits("1", 18))).to.be.revertedWith("math error"); + }); + }); + + // ========================================================================= + // Part 1.6: Full Liquidation End-to-End + // ========================================================================= + describe("6. Full Liquidation End-to-End", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + }); + + it("full liquidation: liquidator repays debt, seizes collateral", async () => { + // Set up user with collateral and borrow at normal prices + await setupPosition(f, f.user, COLLATERAL_AMOUNT, parseUnits("800", 18)); + + // Crash collateral to make user liquidatable at LT + const CRASHED = parseUnits("50", 18); + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(CRASHED); + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenB.address).returns(NORMAL_PRICE); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([CRASHED, CRASHED]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + + // LT: sumCollateral = 0.9 × 50 × 1000 = 45000e18 + // sumBorrow = 100 × 800 = 80000e18 → shortfall = 35000e18 + + // Liquidator repays 50% of 800 = 400e18 + const repayAmount = parseUnits("400", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + + const borrowerDebtBefore = await f.vTokenB.borrowBalanceStored(f.user.address); + const liquidatorCollBefore = await f.vTokenA.balanceOf(f.liquidator.address); + + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "LiquidateBorrow"); + + // Verify borrower debt decreased + const borrowerDebtAfter = await f.vTokenB.borrowBalanceStored(f.user.address); + expect(borrowerDebtAfter).to.be.lt(borrowerDebtBefore); + + // Verify liquidator received seized vTokenA + const liquidatorCollAfter = await f.vTokenA.balanceOf(f.liquidator.address); + expect(liquidatorCollAfter).to.be.gt(liquidatorCollBefore); + }); + + it("liquidation blocked when borrower solvent at spot LT", async () => { + // User borrows moderately + await setupPosition(f, f.user, COLLATERAL_AMOUNT, parseUnits("500", 18)); + + // DBO returns conservative prices (irrelevant for liquidation) + f.dbo.getBoundedPricesView + .whenCalledWith(f.vTokenA.address) + .returns([parseUnits("50", 18), parseUnits("150", 18)]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, parseUnits("150", 18)]); + + // Spot prices normal → LT: 0.9 × 100 × 1000 = 90000 > 100 × 500 = 50000 → solvent + const repayAmount = parseUnits("250", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "Failure"); // INSUFFICIENT_SHORTFALL + }); + }); + + // ========================================================================= + // Part 2: Comptroller-Level Tests + // ========================================================================= + + // ========================================================================= + // Part 2.1: exitMarket with DBO + // ========================================================================= + describe("7. exitMarket with DBO protection", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + }); + + it("exitMarket succeeds with no borrows", async () => { + // Supply collateral only, no borrows + await f.underlyingA.connect(f.user).faucet(COLLATERAL_AMOUNT); + await f.underlyingA.connect(f.user).approve(f.vTokenA.address, COLLATERAL_AMOUNT); + await f.vTokenA.connect(f.user).mint(COLLATERAL_AMOUNT); + await f.comptroller.connect(f.user).enterMarkets([f.vTokenA.address]); + + // Even with conservative DBO prices, exit works (no borrows = no shortfall) + f.dbo.getBoundedPricesView.returns([parseUnits("50", 18), parseUnits("150", 18)]); + + const errCode = await f.comptroller.connect(f.user).callStatic.exitMarket(f.vTokenA.address); + expect(errCode).to.equal(0); // NO_ERROR + }); + + it("exitMarket blocked — bounded prices show shortfall", async () => { + // Supply collateral and borrow + await setupPosition(f, f.user, COLLATERAL_AMOUNT, parseUnits("750", 18)); + await f.comptroller.connect(f.user).enterMarkets([f.vTokenB.address]); + + // DBO bounds conservatively + f.dbo.getBoundedPricesView + .whenCalledWith(f.vTokenA.address) + .returns([parseUnits("80", 18), parseUnits("120", 18)]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, parseUnits("120", 18)]); + + // Exiting vTokenA → all collateral removed → sumCollateral = 0 + // sumBorrow = 120 × 750 = 90000e18 → massive shortfall → REJECTION + const errCode = await f.comptroller.connect(f.user).callStatic.exitMarket(f.vTokenA.address); + expect(errCode).to.not.equal(0); // REJECTION + }); + + it("exitMarket blocked at bounded CF but would be fine at spot LT", async () => { + await setupPosition(f, f.user, COLLATERAL_AMOUNT, parseUnits("750", 18)); + await f.comptroller.connect(f.user).enterMarkets([f.vTokenB.address]); + + // DBO returns conservative bounded: collateral $80, debt $120 + f.dbo.getBoundedPricesView + .whenCalledWith(f.vTokenA.address) + .returns([parseUnits("80", 18), parseUnits("120", 18)]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, parseUnits("120", 18)]); + + // Exit uses CF path (redeemAllowedInternal) → bounded prices → shortfall + const exitErrCode = await f.comptroller.connect(f.user).callStatic.exitMarket(f.vTokenA.address); + expect(exitErrCode).to.not.equal(0); + + // But account is solvent at LT/spot (getAccountLiquidity uses LT path) + const [ltErr, ltLiquidity, ltShortfall] = await f.comptroller.getAccountLiquidity(f.user.address); + expect(ltErr).to.equal(0); + expect(ltLiquidity).to.be.gt(0); + expect(ltShortfall).to.equal(0); + }); + }); + + // ========================================================================= + // Part 2.2: View Function Divergence (CF vs LT path) + // ========================================================================= + describe("8. View Function Divergence — CF vs LT path", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + + // Set up position with borrow + await setupPosition(f, f.user, COLLATERAL_AMOUNT, parseUnits("750", 18)); + + // DBO bounds conservatively: collateral $80, debt $120 + f.dbo.getBoundedPricesView + .whenCalledWith(f.vTokenA.address) + .returns([parseUnits("80", 18), parseUnits("120", 18)]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, parseUnits("120", 18)]); + }); + + it("getBorrowingPower uses bounded prices (CF) → shortfall", async () => { + // CF path: sumCollateral = 0.8 × 80 × 1000 = 64000e18 + // sumBorrow = 120 × 750 = 90000e18 → shortfall = 26000e18 + const [err, liquidity, shortfall] = await f.comptroller.getBorrowingPower(f.user.address); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.be.gt(0); + }); + + it("getAccountLiquidity uses spot prices (LT) → solvent", async () => { + // LT path: sumCollateral = 0.9 × 100 × 1000 = 90000e18 + // sumBorrow = 100 × 750 = 75000e18 → liquidity = 15000e18 + const [err, liquidity, shortfall] = await f.comptroller.getAccountLiquidity(f.user.address); + expect(err).to.equal(0); + expect(liquidity).to.be.gt(0); + expect(shortfall).to.equal(0); + }); + + it("same account: underwater at CF bounded, solvent at LT spot — no premature liquidation", async () => { + // CF path shows shortfall + const [, cfLiquidity, cfShortfall] = await f.comptroller.getBorrowingPower(f.user.address); + expect(cfLiquidity).to.equal(0); + expect(cfShortfall).to.be.gt(0); + + // LT path shows solvency + const [, ltLiquidity, ltShortfall] = await f.comptroller.getAccountLiquidity(f.user.address); + expect(ltLiquidity).to.be.gt(0); + expect(ltShortfall).to.equal(0); + + // Liquidation uses LT path → NOT allowed (solvent at spot) + const repayAmount = parseUnits("375", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "Failure"); // INSUFFICIENT_SHORTFALL + }); + }); + + // ========================================================================= + // Part 2.3: Cross-Path — DBO blocks borrowing but doesn't trigger liquidation + // ========================================================================= + describe("9. Cross-Path: DBO blocks borrowing but does NOT trigger liquidation", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + }); + + it("borrow reverts (CF bounded) but liquidation returns INSUFFICIENT_SHORTFALL (LT spot)", async () => { + await setupPosition(f, f.user, COLLATERAL_AMOUNT, parseUnits("600", 18)); + + // DBO conservative: collateral $70, debt $130 + f.dbo.getBoundedPricesView + .whenCalledWith(f.vTokenA.address) + .returns([parseUnits("70", 18), parseUnits("130", 18)]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, parseUnits("130", 18)]); + + // CF: sumCollateral = 0.8 × 70 × 1000 = 56000e18 + // sumBorrow = 130 × 600 = 78000e18 → shortfall → cannot borrow more + await expect(f.vTokenB.connect(f.user).borrow(parseUnits("1", 18))).to.be.revertedWith("math error"); + + // LT: sumCollateral = 0.9 × 100 × 1000 = 90000e18 + // sumBorrow = 100 × 600 = 60000e18 → solvent → no liquidation + const repayAmount = parseUnits("300", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "Failure"); // INSUFFICIENT_SHORTFALL + }); + }); + + // ========================================================================= + // Part 2.4: claimVenus with DBO + // ========================================================================= + describe("10. claimVenus with DBO (integration verification)", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + await setupPosition(f, f.user, COLLATERAL_AMOUNT, parseUnits("500", 18)); + }); + + it("claimVenus calls updateProtectionState for each entered asset", async () => { + f.dbo.updateProtectionState.reset(); + + // claimVenus → _getAccountLiquidity(USE_COLLATERAL_FACTOR) → _updateProtectionStates + await f.comptroller.connect(f.user)["claimVenus(address)"](f.user.address); + + // updateProtectionState should have been called for vTokenA (entered market) + expect(f.dbo.updateProtectionState).to.have.been.calledWith(f.vTokenA.address); + }); + }); + + // ========================================================================= + // Part 11: Oracle vs DBO Price Divergence Through Protection Lifecycle + // ========================================================================= + describe("11. Oracle vs DBO price divergence through protection lifecycle", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + }); + + it("4-phase cycle: same → diverge (pump) → diverge (stale) → same (disabled)", async () => { + // Phase 1 — Normal: oracle=$100, DBO=[$100,$100] → same + const spotPhase1 = NORMAL_PRICE; + const dboPhase1 = [NORMAL_PRICE, NORMAL_PRICE]; + expect(dboPhase1[0]).to.equal(spotPhase1); + expect(dboPhase1[1]).to.equal(spotPhase1); + + const [, liquidityP1] = await f.comptroller.getBorrowingPower(f.user.address); + expect(liquidityP1).to.equal(parseUnits("80000", 18)); + + // Phase 2 — Pump triggers protection: oracle=$500, DBO=[$100,$500] + const PUMPED = parseUnits("500", 18); + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(PUMPED); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([NORMAL_PRICE, PUMPED]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + + const [, liquidityP2] = await f.comptroller.getBorrowingPower(f.user.address); + expect(liquidityP2).to.equal(parseUnits("80000", 18)); + const [, ltLiqP2] = await f.comptroller.getAccountLiquidity(f.user.address); + expect(ltLiqP2).to.equal(parseUnits("450000", 18)); + + // Phase 3 — Spot normalizes, protection still active: oracle=$100, DBO=[$100,$500] + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(NORMAL_PRICE); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([NORMAL_PRICE, PUMPED]); + + const [, liquidityP3] = await f.comptroller.getBorrowingPower(f.user.address); + expect(liquidityP3).to.equal(parseUnits("80000", 18)); + const [, ltLiqP3] = await f.comptroller.getAccountLiquidity(f.user.address); + expect(ltLiqP3).to.equal(parseUnits("90000", 18)); + + // Phase 4 — Protection disabled: DBO returns [$100,$100] again + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + + const [, liquidityP4] = await f.comptroller.getBorrowingPower(f.user.address); + expect(liquidityP4).to.equal(parseUnits("80000", 18)); + const [, ltLiqP4] = await f.comptroller.getAccountLiquidity(f.user.address); + expect(ltLiqP4).to.equal(parseUnits("90000", 18)); + }); + }); + + // ========================================================================= + // Part 12: Full Lifecycle — Normal → Protect → Block → Disable → Allow + // ========================================================================= + describe("12. Full lifecycle: normal → protect → block → disable → allow", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + }); + + it("complete cycle with balance verification at each step", async () => { + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + + // Step 2: Borrow succeeds at normal prices + const borrowAmount = parseUnits("700", 18); + const uBalBefore = await f.underlyingB.balanceOf(f.user.address); + const borrowBefore = await f.vTokenB.borrowBalanceStored(f.user.address); + await expect(f.vTokenB.connect(f.user).borrow(borrowAmount)).to.emit(f.vTokenB, "Borrow"); + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore.add(borrowAmount)); + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowBefore.add(borrowAmount)); + + // Step 3: Apply conservative DBO prices → actions blocked + const BOUNDED_COLLATERAL = parseUnits("60", 18); + const BOUNDED_DEBT = parseUnits("140", 18); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([BOUNDED_COLLATERAL, BOUNDED_DEBT]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, BOUNDED_DEBT]); + + await expect(f.vTokenB.connect(f.user).borrow(parseUnits("1", 18))).to.be.revertedWith("math error"); + await expect(f.vTokenA.connect(f.user).redeemUnderlying(parseUnits("1", 18))).to.be.revertedWith("math error"); + await expect(f.vTokenA.connect(f.user).transfer(f.attacker.address, parseUnits("1", 18))).to.emit( + f.vTokenA, + "Failure", + ); + + // Step 4: Reset DBO to normal → actions allowed again + resetFakes(f); + + const repayAmount = parseUnits("400", 18); + await f.underlyingB.connect(f.user).faucet(repayAmount); + await f.underlyingB.connect(f.user).approve(f.vTokenB.address, repayAmount); + const borrowBeforeRepay = await f.vTokenB.borrowBalanceStored(f.user.address); + await expect(f.vTokenB.connect(f.user).repayBorrow(repayAmount)).to.emit(f.vTokenB, "RepayBorrow"); + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrowBeforeRepay.sub(repayAmount)); + + const smallBorrow = parseUnits("100", 18); + const uBal2 = await f.underlyingB.balanceOf(f.user.address); + const borrow2 = await f.vTokenB.borrowBalanceStored(f.user.address); + await expect(f.vTokenB.connect(f.user).borrow(smallBorrow)).to.emit(f.vTokenB, "Borrow"); + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBal2.add(smallBorrow)); + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.equal(borrow2.add(smallBorrow)); + + const redeemAmt = parseUnits("50", 18); + const vBal = await f.vTokenA.balanceOf(f.user.address); + const uBalA = await f.underlyingA.balanceOf(f.user.address); + await expect(f.vTokenA.connect(f.user).redeemUnderlying(redeemAmt)).to.emit(f.vTokenA, "Redeem"); + expect(await f.vTokenA.balanceOf(f.user.address)).to.equal(vBal.sub(redeemAmt)); + expect(await f.underlyingA.balanceOf(f.user.address)).to.equal(uBalA.add(redeemAmt)); + }); + }); + + // ========================================================================= + // Part 13: Multi-Asset Protection Independence + // ========================================================================= + describe("13. Multi-asset protection independence", () => { + let f: RealVTokenFixture; + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + }); + + it("conservative DBO on vTokenA blocks borrow, normal DBO on vTokenB allows borrow", async () => { + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + + // Conservative prices only for vTokenA + const BOUNDED_COLLATERAL = parseUnits("50", 18); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([BOUNDED_COLLATERAL, NORMAL_PRICE]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + + // User: sumCollateral = 0.8 × 50 × 1000 = 40000e18. Borrow 500e18 = 50000e18 > 40000 → blocked + await expect(f.vTokenB.connect(f.user).borrow(parseUnits("500", 18))).to.be.revertedWith("math error"); + + // Attacker: collateral in vTokenB (normal prices), borrow from vTokenA + await f.underlyingA.setVariable("_balances", { [f.vTokenA.address]: POOL_LIQUIDITY }); + await f.vTokenA.harnessSetInternalCash(POOL_LIQUIDITY); + + await f.underlyingB.connect(f.attacker).faucet(COLLATERAL_AMOUNT); + await f.underlyingB.connect(f.attacker).approve(f.vTokenB.address, COLLATERAL_AMOUNT); + await f.vTokenB.connect(f.attacker).mint(COLLATERAL_AMOUNT); + await f.comptroller.connect(f.attacker).enterMarkets([f.vTokenB.address]); + + const attackerBorrow = parseUnits("700", 18); + const uBalBefore = await f.underlyingA.balanceOf(f.attacker.address); + const borrowBefore = await f.vTokenA.borrowBalanceStored(f.attacker.address); + await expect(f.vTokenA.connect(f.attacker).borrow(attackerBorrow)).to.emit(f.vTokenA, "Borrow"); + expect(await f.underlyingA.balanceOf(f.attacker.address)).to.equal(uBalBefore.add(attackerBorrow)); + expect(await f.vTokenA.borrowBalanceStored(f.attacker.address)).to.equal(borrowBefore.add(attackerBorrow)); + }); + }); + + // ========================================================================= + // Part 14: Extreme Volatility — Price Swings Past Max AND Below Min + // ========================================================================= + describe("14. Extreme volatility — price swings past max and below min", () => { + /* + * Simulates a volatile market where price: + * 1. Starts at $100 + * 2. Pumps to $300 → window max expands to $300, min stays $100 + * 3. Crashes to $10 → window min contracts to $10, max stays $300 + * 4. Window is now [$10, $300] — extremely wide + * + * DBO at extreme state: + * collateral = min(spot, windowMin) = min($10, $10) = $10 + * debt = max(spot, windowMax) = max($10, $300) = $300 + */ + const PUMPED_EXTREME = parseUnits("300", 18); + const CRASHED_EXTREME = parseUnits("10", 18); + + let f: RealVTokenFixture; + + // Helper: apply extreme volatility — price pumped then crashed + // Both markets affected: vTokenA collateral crushed, vTokenB debt inflated + function applyExtremeVolatility(): void { + // vTokenA spot crashed to $10 + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(CRASHED_EXTREME); + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenB.address).returns(NORMAL_PRICE); + // DBO: vTokenA window [$10, $300] → collateral=$10, debt=$300 + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([CRASHED_EXTREME, PUMPED_EXTREME]); + // DBO: vTokenB debt also inflated to $300 (simulates correlated volatility) + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, PUMPED_EXTREME]); + } + + beforeEach(async () => { + f = await loadFixture(deployRealVTokenFixture); + resetFakes(f); + await setupPosition(f, f.user, COLLATERAL_AMOUNT); + }); + + it("borrowing power collapses through volatility stages", async () => { + // Stage 1 — Normal: liquidity = 0.8 × 100 × 1000 = 80000e18 + const [, liqNormal] = await f.comptroller.getBorrowingPower(f.user.address); + expect(liqNormal).to.equal(parseUnits("80000", 18)); + + // Stage 2 — Pump to $300: DBO [$100,$300] → collateral still capped at $100 + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(PUMPED_EXTREME); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([NORMAL_PRICE, PUMPED_EXTREME]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + + const [, liqPump] = await f.comptroller.getBorrowingPower(f.user.address); + expect(liqPump).to.equal(parseUnits("80000", 18)); // unchanged — bounded at $100 + + // Stage 3 — Crash to $10: DBO [$10,$300] → collateral at $10, debt at $300 + applyExtremeVolatility(); + + const [, liqExtreme] = await f.comptroller.getBorrowingPower(f.user.address); + // sumCollateral = 0.8 × 10 × 1000 = 8000e18, no borrow → liquidity = 8000e18 + expect(liqExtreme).to.equal(parseUnits("8000", 18)); + + // Capacity collapsed: 80000 → 80000 → 8000 (90% drop from normal) + expect(liqNormal.sub(liqExtreme)).to.equal(parseUnits("72000", 18)); + }); + + it("borrow blocked — extreme collateral devaluation + debt inflation", async () => { + applyExtremeVolatility(); + + // sumCollateral = 0.8 × 10 × 1000 = 8000e18 + // Borrow 50e18: sumBorrow = 300 × 50 = 15000e18 > 8000e18 → shortfall (debt inflated at $300) + await expect(f.vTokenB.connect(f.user).borrow(parseUnits("50", 18))).to.be.revertedWith("math error"); + + // Even tiny borrow: 30e18 × $300 = 9000e18 > 8000e18 → still blocked + await expect(f.vTokenB.connect(f.user).borrow(parseUnits("30", 18))).to.be.revertedWith("math error"); + + // Only borrow < 8000/300 ≈ 26.67e18 would succeed + const tinyBorrow = parseUnits("20", 18); + const uBalBefore = await f.underlyingB.balanceOf(f.user.address); + await expect(f.vTokenB.connect(f.user).borrow(tinyBorrow)).to.emit(f.vTokenB, "Borrow"); + expect(await f.underlyingB.balanceOf(f.user.address)).to.equal(uBalBefore.add(tinyBorrow)); + }); + + it("redeem blocked — existing borrow + extreme volatility", async () => { + // Borrow at normal prices first + await f.vTokenB.connect(f.user).borrow(parseUnits("100", 18)); + + // Apply extreme volatility + applyExtremeVolatility(); + + // sumCollateral = 0.8 × 10 × 1000 = 8000e18 + // sumBorrow = 300 × 100 = 30000e18 → deep shortfall = 22000e18 + // Any redeem makes it worse + await expect(f.vTokenA.connect(f.user).redeemUnderlying(parseUnits("1", 18))).to.be.revertedWith("math error"); + }); + + it("liquidation at spot — crash severe enough to make user underwater at LT", async () => { + // Borrow at normal prices: 100e18 at $100 = $10000 debt + await f.vTokenB.connect(f.user).borrow(parseUnits("100", 18)); + + applyExtremeVolatility(); + + // LT path uses spot: sumCollateral = 0.9 × 10 × 1000 = 9000e18 + // sumBorrow (spot $100 for vTokenB) = 100 × 100 = 10000e18 → shortfall = 1000e18 + // → liquidation should succeed + const repayAmount = parseUnits("50", 18); + await f.underlyingB.connect(f.liquidator).faucet(repayAmount); + await f.underlyingB.connect(f.liquidator).approve(f.vTokenB.address, repayAmount); + + const debtBefore = await f.vTokenB.borrowBalanceStored(f.user.address); + const seizedBefore = await f.vTokenA.balanceOf(f.liquidator.address); + + await expect( + f.vTokenB.connect(f.liquidator).liquidateBorrow(f.user.address, repayAmount, f.vTokenA.address), + ).to.emit(f.vTokenB, "LiquidateBorrow"); + + expect(await f.vTokenB.borrowBalanceStored(f.user.address)).to.be.lt(debtBefore); + expect(await f.vTokenA.balanceOf(f.liquidator.address)).to.be.gt(seizedBefore); + }); + + it("borrowing power comparison through full volatility cycle", async () => { + // Borrow 50e18 at normal prices first + await f.vTokenB.connect(f.user).borrow(parseUnits("50", 18)); + + // Normal: sumCollateral = 80000, sumBorrow = 100 × 50 = 5000 → liquidity = 75000 + const [, liq1] = await f.comptroller.getBorrowingPower(f.user.address); + expect(liq1).to.equal(parseUnits("75000", 18)); + + // Pump to $300: DBO collateral capped at $100 → sumCollateral = 80000, sumBorrow = 100 × 50 = 5000 + f.oracle.getUnderlyingPrice.whenCalledWith(f.vTokenA.address).returns(PUMPED_EXTREME); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenA.address).returns([NORMAL_PRICE, PUMPED_EXTREME]); + f.dbo.getBoundedPricesView.whenCalledWith(f.vTokenB.address).returns([NORMAL_PRICE, NORMAL_PRICE]); + + const [, liq2] = await f.comptroller.getBorrowingPower(f.user.address); + // sumCollateral = 0.8 × 100 × 1000 = 80000, sumBorrow = 100 × 50 = 5000 → 75000 + expect(liq2).to.equal(parseUnits("75000", 18)); + + // Extreme crash to $10: DBO [$10,$300] → collateral=$10, debt=$300 + applyExtremeVolatility(); + + const [, liq3, shortfall3] = await f.comptroller.getBorrowingPower(f.user.address); + // sumCollateral = 0.8 × 10 × 1000 = 8000, sumBorrow = 300 × 50 = 15000 → shortfall = 7000 + expect(liq3).to.equal(0); + // Full cycle: 75000 → 75000 → shortfall 7000 + // Shows DBO caps upside during pump but amplifies downside during crash + // because window max stays inflated ($300) while collateral tracks down ($10) + expect(shortfall3).to.equal(parseUnits("7000", 18)); + }); + }); +}); diff --git a/tests/hardhat/Comptroller/Diamond/repaymentMethod.ts b/tests/hardhat/Comptroller/Diamond/repaymentMethod.ts index 0484066ae..a6577844d 100644 --- a/tests/hardhat/Comptroller/Diamond/repaymentMethod.ts +++ b/tests/hardhat/Comptroller/Diamond/repaymentMethod.ts @@ -11,6 +11,7 @@ import { ComptrollerLens__factory, ComptrollerMock, IAccessControlManagerV5, + IDeviationBoundedOracle, IProtocolShareReserve, InterestRateModel, PriceOracle, @@ -68,6 +69,10 @@ describe("RepayBorrow Capping Logic Tests", async () => { await comptroller._setComptrollerLens(comptrollerLens.address); await comptroller._setPriceOracle(oracle.address); + const dbo = await smock.fake("IDeviationBoundedOracle"); + dbo.getBoundedPricesView.returns([convertToUnit(1, 18), convertToUnit(1, 18)]); + await comptroller.setDeviationBoundedOracle(dbo.address); + // Create underlying token const underlyingFactory = await smock.mock("BEP20Harness"); underlying = await underlyingFactory.deploy(0, "Test Token", 18, "TEST"); diff --git a/tests/hardhat/Comptroller/Diamond/scripts/deploy.ts b/tests/hardhat/Comptroller/Diamond/scripts/deploy.ts index b3fc7533e..57c9df1d6 100644 --- a/tests/hardhat/Comptroller/Diamond/scripts/deploy.ts +++ b/tests/hardhat/Comptroller/Diamond/scripts/deploy.ts @@ -19,12 +19,17 @@ export async function deployFacets() { // deploy facets const FacetNames = ["MarketFacet", "PolicyFacet", "RewardFacet", "SetterFacet", "FlashLoanFacet"]; const cut: any = []; + let rewardFacetAddress = ""; for (const FacetName of FacetNames) { const Facet = await ethers.getContractFactory(FacetName); const facet = await Facet.deploy(); await facet.deployed(); + if (FacetName === "RewardFacet") { + rewardFacetAddress = facet.address; + } + const FacetInterface = await ethers.getContractAt(`I${FacetName}`, facet.address); cut.push({ @@ -34,6 +39,16 @@ export async function deployFacets() { }); } + // IFacetBase selectors are inlined into every facet (each inherits FacetBase) but must be + // registered exactly once on the diamond. Route them through RewardFacet's address to match + // how they used to be picked up via `IRewardFacet is IFacetBase` (before param generator script change). + const FacetBaseInterface = await ethers.getContractAt("IFacetBase", rewardFacetAddress); + cut.push({ + facetAddress: rewardFacetAddress, + action: FacetCutAction.Add, + functionSelectors: getSelectors(FacetBaseInterface), + }); + return { diamond, cut, diff --git a/tests/hardhat/EvilXToken.ts b/tests/hardhat/EvilXToken.ts index 183fd05be..64ed7a40b 100644 --- a/tests/hardhat/EvilXToken.ts +++ b/tests/hardhat/EvilXToken.ts @@ -3,7 +3,12 @@ import chai from "chai"; import { ethers } from "hardhat"; import { convertToUnit } from "../../helpers/utils"; -import { ComptrollerHarness__factory, IAccessControlManagerV8, IProtocolShareReserve } from "../../typechain"; +import { + ComptrollerHarness__factory, + IAccessControlManagerV8, + IDeviationBoundedOracle, + IProtocolShareReserve, +} from "../../typechain"; const { expect } = chai; @@ -39,6 +44,8 @@ describe("Evil Token test", async () => { const priceOracleFactory = await ethers.getContractFactory("SimplePriceOracle"); const priceOracle = await priceOracleFactory.deploy(); await priceOracle.deployed(); + const deviationBoundedOracle = await smock.fake("IDeviationBoundedOracle"); + deviationBoundedOracle.getBoundedPricesView.returns([convertToUnit(1, 18), convertToUnit(1, 18)]); const xvsFactory = await ethers.getContractFactory("XVS"); const xvs = await xvsFactory.deploy(root.address); @@ -54,6 +61,7 @@ describe("Evil Token test", async () => { await unitroller._setAccessControl(accessControlMock.address); await unitroller._setCloseFactor(convertToUnit(0.8, 18)); await unitroller._setPriceOracle(priceOracle.address); + await unitroller.setDeviationBoundedOracle(deviationBoundedOracle.address); await unitroller._setComptrollerLens(comptrollerLens.address); await unitroller.setXVSAddress(xvs.address); // harness only await unitroller.harnessSetVenusRate(venusRate); diff --git a/tests/hardhat/Fork/BUSDLiquidator.ts b/tests/hardhat/Fork/BUSDLiquidator.ts index 3be9d1222..b592b5e98 100644 --- a/tests/hardhat/Fork/BUSDLiquidator.ts +++ b/tests/hardhat/Fork/BUSDLiquidator.ts @@ -11,6 +11,7 @@ import { ComptrollerMock, FaucetToken, IAccessControlManagerV8__factory, + IDeviationBoundedOracle, VBep20, } from "../../../typechain"; import { @@ -153,6 +154,9 @@ const setupFork = async (): Promise => { }); const timelock = await initMainnetUser(addresses.bscmainnet.TIMELOCK, parseEther("1")); + const deviationBoundedOracle = await smock.fake("IDeviationBoundedOracle"); + deviationBoundedOracle.getBoundedPricesView.returns([parseUnits("1", 18), parseUnits("1", 18)]); + await comptroller.connect(timelock).setDeviationBoundedOracle(deviationBoundedOracle.address); await acm .connect(timelock) .giveCallPermission(comptroller.address, "_setActionsPaused(address[],uint8[],bool)", busdLiquidator.address); @@ -203,6 +207,10 @@ const test = (setup: () => Promise) => () => { [, , borrower, someone] = await ethers.getSigners(); }); + it("configures a deviation bounded oracle", async () => { + expect(await comptroller.deviationBoundedOracle()).to.not.equal(ethers.constants.AddressZero); + }); + describe("setLiquidatorShare", () => { it("should set liquidator share", async () => { const newLiquidatorShareMantissa = parseUnits("1.0", 18); diff --git a/tests/hardhat/Fork/TokenRedeemer.ts b/tests/hardhat/Fork/TokenRedeemer.ts index d0ddb7ad3..3f6e857d4 100644 --- a/tests/hardhat/Fork/TokenRedeemer.ts +++ b/tests/hardhat/Fork/TokenRedeemer.ts @@ -9,6 +9,7 @@ import { ethers } from "hardhat"; import { FaucetToken, + IDeviationBoundedOracle, TokenRedeemer, TokenRedeemer__factory, VAI, @@ -177,6 +178,9 @@ const setupFork = async (): Promise => { const treasury = await initMainnetUser(treasuryAddress, SUPPLIED_AMOUNT.mul(2).add(parseEther("3"))); const timelock = await initMainnetUser(addresses.bscmainnet.TIMELOCK, parseEther("1")); + const deviationBoundedOracle = await smock.fake("IDeviationBoundedOracle"); + deviationBoundedOracle.getBoundedPricesView.returns([parseUnits("1", 18), parseUnits("1", 18)]); + await comptroller.connect(timelock).setDeviationBoundedOracle(deviationBoundedOracle.address); const redeemer = await deployTokenRedeemer(timelock, vBNB); await comptroller.connect(timelock)._setMarketSupplyCaps([vToken.address], [ethers.constants.MaxUint256]); const actions = { MINT: 0, ENTER_MARKET: 7 }; diff --git a/tests/hardhat/Fork/deviationBoundedOracleFork.ts b/tests/hardhat/Fork/deviationBoundedOracleFork.ts new file mode 100644 index 000000000..e0441f7cd --- /dev/null +++ b/tests/hardhat/Fork/deviationBoundedOracleFork.ts @@ -0,0 +1,2379 @@ +import { FakeContract, smock } from "@defi-wonderland/smock"; +import { setBalance, time } from "@nomicfoundation/hardhat-network-helpers"; +import chai from "chai"; +import { Signer } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers, upgrades } from "hardhat"; + +import { FacetCutAction, getSelectors } from "../../../script/deploy/comptroller/diamond"; +import { + BEP20__factory, + ComptrollerMock, + ComptrollerMock__factory, + Diamond, + Diamond__factory, + IAccessControlManagerV8, + IAccessControlManagerV8__factory, + Unitroller__factory, +} from "../../../typechain"; +import { ResilientOracleInterface } from "../../../typechain/@venusprotocol/oracle/contracts/interfaces/OracleInterface.sol/ResilientOracleInterface"; +import { FORK_MAINNET, forking, initMainnetUser } from "./utils"; + +const { expect } = chai; +chai.use(smock.matchers); + +// --------------------------------------------------------------------------- +// BSC Mainnet Addresses +// --------------------------------------------------------------------------- +const COMPTROLLER = "0xfD36E2c2a6789Db23113685031d7F16329158384"; +const NORMAL_TIMELOCK = "0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396"; +const ACM = "0x4788629ABc6cFCA10F9f969efdEAa1cF70c23555"; + +const VAI = "0x4BD17003473389A42DAF6a0a729f6Fdb328BbBd7"; + +// vTokens +const vBNB_ADDRESS = "0xA07c5b74C9B40447a954e1466938b865b6BBea36"; +const vUSDT_ADDRESS = "0xfD5840Cd36d94D7229439859C0112a4185BC0255"; +const vBTC_ADDRESS = "0x882C173bC7Ff3b7786CA16dfeD3DFFfb9Ee7847B"; + +// Underlying +const USDT_ADDR = "0x55d398326f99059fF775485246999027B3197955"; +const BTCB_ADDR = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; +const WBNB_ADDR = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; + +// Token holders (whales) — Binance hot wallet +const USDT_WHALE = "0xF977814e90dA44bFA03b6295A0616a897441aceC"; +const BTCB_WHALE = "0xF977814e90dA44bFA03b6295A0616a897441aceC"; + +// --------------------------------------------------------------------------- +// Deterministic Prices (18 decimals) +// --------------------------------------------------------------------------- +const USDT_PRICE = parseUnits("1", 18); // $1 +const BTCB_PRICE = parseUnits("60000", 18); // $60,000 +const WBNB_PRICE = parseUnits("600", 18); // $600 + +// Pump/crash variants +const USDT_PUMPED = parseUnits("1.5", 18); // $1.50 (+50%, triggers 16.67% threshold) +const BTCB_CRASHED = parseUnits("42000", 18); // $42,000 (-30%, triggers threshold) +const BTCB_PUMPED = parseUnits("90000", 18); // $90,000 (+50%, triggers BTC protection) + +// DBO configuration +const COOLDOWN_PERIOD = 3600; // 1 hour +const TRIGGER_THRESHOLD = parseUnits("0.1667", 18); // 16.67% +const RESET_THRESHOLD = parseUnits("0.05", 18); // 5% + +// Existing user with positions +const USER_WITH_POSITIONS = "0x50c6047B6F3EeC1aeDDa257A9065f91CF68A3b68"; + +// --------------------------------------------------------------------------- +// Shared State +// --------------------------------------------------------------------------- +let timelock: Signer; +let comptroller: ComptrollerMock; +let diamond: Diamond; +let acm: IAccessControlManagerV8; +let dbo: any; // DeviationBoundedOracle +let fakeOracle: FakeContract; +let vUSDT: any; // VBep20Delegate ABI for Failure event access +let vBTC: any; +let user: Signer; + +// --------------------------------------------------------------------------- +// Helper: Upgrade Diamond Comptroller (follows emodeUpgrade.ts) +// --------------------------------------------------------------------------- +async function upgradeComptroller(): Promise { + const DiamondFactory = await ethers.getContractFactory("Diamond"); + const newDiamond = await DiamondFactory.deploy(); + + const Unitroller = Unitroller__factory.connect(COMPTROLLER, timelock); + await Unitroller._setPendingImplementation(newDiamond.address); + await newDiamond.connect(timelock)._become(Unitroller.address); + + diamond = Diamond__factory.connect(COMPTROLLER, timelock); + + // Step 1: Remove ALL existing facets + const removeCut: any[] = []; + const existingFacets = await diamond.facets(); + for (const facet of existingFacets) { + removeCut.push({ + facetAddress: ethers.constants.AddressZero, + action: FacetCutAction.Remove, + functionSelectors: facet.functionSelectors, + }); + } + await diamond.diamondCut(removeCut); + + // Step 2: Deploy and add new facets with global deduplication + const addCut: any[] = []; + const allAddedSelectors = new Set(); + + const FacetNames = ["MarketFacet", "PolicyFacet", "SetterFacet", "RewardFacet", "FlashLoanFacet"]; + const deployedFacets: Record = {}; + + for (const FacetName of FacetNames) { + const Facet = await ethers.getContractFactory(FacetName); + const facet = await Facet.deploy(); + await facet.deployed(); + deployedFacets[FacetName] = facet.address; + + const facetInterface = await ethers.getContractAt(`I${FacetName}`, facet.address); + const rawSelectors: string[] = getSelectors(facetInterface); + const selectors = rawSelectors.filter((s: string) => !allAddedSelectors.has(s)); + for (const s of selectors) allAddedSelectors.add(s); + + if (selectors.length > 0) { + addCut.push({ + facetAddress: facet.address, + action: FacetCutAction.Add, + functionSelectors: selectors, + }); + } + } + + // Add IFacetBase selectors via MarketFacet (common getters) + const baseIface = await ethers.getContractAt("IFacetBase", deployedFacets["MarketFacet"]); + const baseRaw: string[] = getSelectors(baseIface); + const baseSelectors = baseRaw.filter((s: string) => !allAddedSelectors.has(s)); + for (const s of baseSelectors) allAddedSelectors.add(s); + + if (baseSelectors.length > 0) { + addCut.push({ + facetAddress: deployedFacets["MarketFacet"], + action: FacetCutAction.Add, + functionSelectors: baseSelectors, + }); + } + + await diamond.diamondCut(addCut); + + const comptrollerInstance = ComptrollerMock__factory.connect(COMPTROLLER, timelock); + + // Deploy and set new ComptrollerLens (has _calculateAccountPosition with DBO calls) + const ComptrollerLens = await ethers.getContractFactory("ComptrollerLens"); + const lens = await ComptrollerLens.deploy(); + await comptrollerInstance._setComptrollerLens(lens.address); + + return comptrollerInstance; +} + +// --------------------------------------------------------------------------- +// Helper: Deploy DeviationBoundedOracle (transparent proxy) +// --------------------------------------------------------------------------- +async function deployDBO(oracleAddress: string): Promise { + const DBOFactory = await ethers.getContractFactory("DeviationBoundedOracle"); + const dbo = await upgrades.deployProxy(DBOFactory, [ACM], { + constructorArgs: [oracleAddress, vBNB_ADDRESS, VAI], + initializer: "initialize", + unsafeAllow: ["state-variable-immutable"], + }); + return dbo; +} + +// --------------------------------------------------------------------------- +// Helper: Configure fake oracle with deterministic prices +// --------------------------------------------------------------------------- +function setupDefaultPrices(): void { + // getPrice(asset) — used by DBO._fetchSpotPrice() + fakeOracle.getPrice.whenCalledWith(USDT_ADDR).returns(USDT_PRICE); + fakeOracle.getPrice.whenCalledWith(BTCB_ADDR).returns(BTCB_PRICE); + fakeOracle.getPrice.whenCalledWith(WBNB_ADDR).returns(WBNB_PRICE); + + // getUnderlyingPrice(vToken) — used by ComptrollerLens LT path + fakeOracle.getUnderlyingPrice.whenCalledWith(vUSDT_ADDRESS).returns(USDT_PRICE); + fakeOracle.getUnderlyingPrice.whenCalledWith(vBTC_ADDRESS).returns(BTCB_PRICE); + fakeOracle.getUnderlyingPrice.whenCalledWith(vBNB_ADDRESS).returns(WBNB_PRICE); +} + +function pumpUSDTPrice(): void { + fakeOracle.getPrice.whenCalledWith(USDT_ADDR).returns(USDT_PUMPED); + fakeOracle.getUnderlyingPrice.whenCalledWith(vUSDT_ADDRESS).returns(USDT_PUMPED); +} + +function crashBTCBPrice(): void { + fakeOracle.getPrice.whenCalledWith(BTCB_ADDR).returns(BTCB_CRASHED); + fakeOracle.getUnderlyingPrice.whenCalledWith(vBTC_ADDRESS).returns(BTCB_CRASHED); +} + +function resetPrices(): void { + setupDefaultPrices(); +} + +function pumpBTCBPrice(): void { + fakeOracle.getPrice.whenCalledWith(BTCB_ADDR).returns(BTCB_PUMPED); + fakeOracle.getUnderlyingPrice.whenCalledWith(vBTC_ADDRESS).returns(BTCB_PUMPED); +} + +// --------------------------------------------------------------------------- +// Helper: Grant all necessary ACM permissions +// --------------------------------------------------------------------------- +async function grantPermissions(): Promise { + const timelockAddr = await timelock.getAddress(); + const comptrollerPerms = [ + "setDeviationBoundedOracle(address)", + "_setComptrollerLens(address)", + "_setPriceOracle(address)", + "setCollateralFactor(address,uint256,uint256)", + "setLiquidationIncentive(address,uint256)", + "setMarketSupplyCaps(address[],uint256[])", + "setMarketBorrowCaps(address[],uint256[])", + "setIsBorrowAllowed(uint96,address,bool)", + "_setActionsPaused(address[],uint8[],bool)", + ]; + for (const perm of comptrollerPerms) { + await acm.giveCallPermission(COMPTROLLER, perm, timelockAddr); + } +} + +async function grantDBOPermissions(dboAddress: string): Promise { + const timelockAddr = await timelock.getAddress(); + const dboPerms = [ + "setTokenConfig(address,uint64,uint256,uint256,bool)", + "disableActiveProtectedPrice(address)", + "updateMinPrice(address,uint128)", + "updateMaxPrice(address,uint128)", + "setThresholds(address,uint256,uint256)", + "setCooldownPeriod(address,uint64)", + "setAssetBoundedPricingEnabled(address,bool)", + ]; + for (const perm of dboPerms) { + await acm.giveCallPermission(dboAddress, perm, timelockAddr); + } +} + +// --------------------------------------------------------------------------- +// Helper: Neutralize DBO state — reset windows, disable protection, restore defaults +// --------------------------------------------------------------------------- +async function neutralizeDBO(): Promise { + resetPrices(); // oracle returns $1 USDT, $60k BTC, $600 WBNB + + // Advance time past any cooldown (covers extended cooldowns from prior tests) + await time.increase(COOLDOWN_PERIOD * 10); + + for (const [asset, price] of [ + [USDT_ADDR, USDT_PRICE], + [BTCB_ADDR, BTCB_PRICE], + [WBNB_ADDR, WBNB_PRICE], + ] as [string, any][]) { + // Narrow window to ±1% of spot (always satisfies keeper constraints) + const neutralMin = price.mul(99).div(100); + const neutralMax = price.mul(101).div(100); + + await dbo.connect(timelock).updateMinPrice(asset, neutralMin); + await dbo.connect(timelock).updateMaxPrice(asset, neutralMax); + + // Disable protection if active (range = 2% < 5% reset threshold, cooldown elapsed) + const cfg = await dbo.assetProtectionConfig(asset); + if (cfg.currentlyUsingProtectedPrice) { + await dbo.connect(timelock).disableActiveProtectedPrice(asset); + } + } + + // Restore default thresholds and cooldown + for (const asset of [USDT_ADDR, BTCB_ADDR, WBNB_ADDR]) { + await dbo.connect(timelock).setThresholds(asset, TRIGGER_THRESHOLD, RESET_THRESHOLD); + await dbo.connect(timelock).setCooldownPeriod(asset, COOLDOWN_PERIOD); + } +} + +// =========================================================================== +// Fork Tests +// =========================================================================== +if (FORK_MAINNET) { + forking(90924377, () => { + describe("DeviationBoundedOracle Fork Integration Tests", () => { + before(async () => { + // Impersonate timelock + timelock = await initMainnetUser(NORMAL_TIMELOCK, parseUnits("10")); + const [signer1] = await ethers.getSigners(); + user = signer1; + + // Get vTokens + vUSDT = await ethers.getContractAt("contracts/Tokens/VTokens/VBep20Delegate.sol:VBep20Delegate", vUSDT_ADDRESS); + vBTC = await ethers.getContractAt("contracts/Tokens/VTokens/VBep20Delegate.sol:VBep20Delegate", vBTC_ADDRESS); + + // Get ACM + acm = IAccessControlManagerV8__factory.connect(ACM, timelock); + + // 1. Upgrade comptroller with DBO-aware facets + lens + comptroller = await upgradeComptroller(); + await grantPermissions(); + + // 2. Create fake oracle with deterministic prices + fakeOracle = await smock.fake("ResilientOracleInterface"); + setupDefaultPrices(); + + // 3. Set fake oracle as comptroller's oracle (for LT path) + await comptroller._setPriceOracle(fakeOracle.address); + + // 4. Deploy DBO with fake oracle (for CF path spot price fetching) + dbo = await deployDBO(fakeOracle.address); + await grantDBOPermissions(dbo.address); + + // 5. Ensure borrow is allowed and markets are active + await comptroller.setIsBorrowAllowed(0, vUSDT_ADDRESS, true); + await comptroller.setIsBorrowAllowed(0, vBTC_ADDRESS, true); + + // 6. Configure DBO tokens (setTokenConfig calls getPrice internally) + await dbo + .connect(timelock) + .setTokenConfig(USDT_ADDR, COOLDOWN_PERIOD, TRIGGER_THRESHOLD, RESET_THRESHOLD, true); + await dbo + .connect(timelock) + .setTokenConfig(BTCB_ADDR, COOLDOWN_PERIOD, TRIGGER_THRESHOLD, RESET_THRESHOLD, true); + await dbo + .connect(timelock) + .setTokenConfig(WBNB_ADDR, COOLDOWN_PERIOD, TRIGGER_THRESHOLD, RESET_THRESHOLD, true); + + // 7. Wire DBO into comptroller + await comptroller.setDeviationBoundedOracle(dbo.address); + }); + + // ===================================================================== + // Part 1: Setup Verification + // ===================================================================== + describe("1. Setup Verification", () => { + it("DBO is correctly set on comptroller", async () => { + expect(await comptroller.deviationBoundedOracle()).to.equal(dbo.address); + }); + + it("DBO token configs are initialized with correct spot prices", async () => { + const usdtConfig = await dbo.assetProtectionConfig(USDT_ADDR); + expect(usdtConfig.asset).to.equal(USDT_ADDR); + expect(usdtConfig.isBoundedPricingEnabled).to.be.true; + expect(usdtConfig.currentlyUsingProtectedPrice).to.be.false; + // minPrice and maxPrice should be USDT_PRICE (deterministic $1) + expect(usdtConfig.minPrice).to.equal(USDT_PRICE); + expect(usdtConfig.maxPrice).to.equal(USDT_PRICE); + }); + + it("existing vTokens work correctly with upgraded comptroller", async () => { + const market = await comptroller.markets(vUSDT_ADDRESS); + expect(market.isListed).to.be.true; + }); + + it("view functions work after upgrade", async () => { + const [err] = await comptroller.getAccountLiquidity(USER_WITH_POSITIONS); + expect(err).to.equal(0); + }); + }); + + // ===================================================================== + // Part 2: Normal Operation — DBO Active, No Protection + // ===================================================================== + describe("2. Normal Operation — no protection active", () => { + it("user can supply collateral via vToken.mint()", async () => { + const amount = parseUnits("100", 18); + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(await user.getAddress(), amount); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, user); + await usdtUser.approve(vUSDT_ADDRESS, amount); + + const vBalBefore = await vUSDT.balanceOf(await user.getAddress()); + const uBalBefore = await usdtUser.balanceOf(await user.getAddress()); + const er = await vUSDT.callStatic.exchangeRateCurrent(); + const expectedVTokens = amount.mul(parseUnits("1", 18)).div(er); + + await expect(vUSDT.connect(user).mint(amount)).to.emit(vUSDT, "Mint"); + + expect(await vUSDT.balanceOf(await user.getAddress())).to.be.closeTo( + vBalBefore.add(expectedVTokens), + parseUnits("1", 8), + ); + expect(await usdtUser.balanceOf(await user.getAddress())).to.equal(uBalBefore.sub(amount)); + }); + + it("user can borrow via vToken.borrow() with real collateral", async () => { + await comptroller.connect(user).enterMarkets([vUSDT_ADDRESS]); + // 100 USDT at $1, CF=0.8 → $80 capacity. BTC at $60k → borrow 0.001 BTC = $60 + const borrowAmount = parseUnits("0.001", 18); + const btcb = BEP20__factory.connect(BTCB_ADDR, user); + const uBalBefore = await btcb.balanceOf(await user.getAddress()); + const borrowBefore = await vBTC.borrowBalanceStored(await user.getAddress()); + + await expect(vBTC.connect(user).borrow(borrowAmount)).to.emit(vBTC, "Borrow"); + + expect(await btcb.balanceOf(await user.getAddress())).to.equal(uBalBefore.add(borrowAmount)); + expect(await vBTC.borrowBalanceStored(await user.getAddress())).to.be.closeTo( + borrowBefore.add(borrowAmount), + parseUnits("0.000001", 18), + ); + }); + + it("user can repay via vToken.repayBorrow()", async () => { + const userAddr = await user.getAddress(); + const debt = await vBTC.callStatic.borrowBalanceCurrent(userAddr); + if (debt.gt(0)) { + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(userAddr, debt.mul(2)); + + const btcbUser = BEP20__factory.connect(BTCB_ADDR, user); + await btcbUser.approve(vBTC_ADDRESS, debt.mul(2)); + + const borrowBefore = await vBTC.borrowBalanceStored(userAddr); + const uBalBefore = await btcbUser.balanceOf(userAddr); + await expect(vBTC.connect(user).repayBorrow(debt)).to.emit(vBTC, "RepayBorrow"); + + expect(await vBTC.borrowBalanceStored(userAddr)).to.be.closeTo( + borrowBefore.sub(debt), + parseUnits("0.000001", 18), + ); + expect(await btcbUser.balanceOf(userAddr)).to.equal(uBalBefore.sub(debt)); + } + }); + + it("user can redeem via vToken.redeemUnderlying()", async () => { + const userAddr = await user.getAddress(); + const usdtUser = BEP20__factory.connect(USDT_ADDR, user); + const redeemAmount = parseUnits("10", 18); + + const uBalBefore = await usdtUser.balanceOf(userAddr); + await expect(vUSDT.connect(user).redeemUnderlying(redeemAmount)).to.emit(vUSDT, "Redeem"); + + expect(await usdtUser.balanceOf(userAddr)).to.equal(uBalBefore.add(redeemAmount)); + }); + + it("user can transfer vTokens when solvent", async () => { + const userAddr = await user.getAddress(); + const dst = ethers.Wallet.createRandom().connect(ethers.provider); + const dstAddr = await dst.getAddress(); + // Use very small amount — prior tests may have consumed balance + const srcBalance = await vUSDT.balanceOf(userAddr); + const transferAmount = srcBalance.div(10); // 10% of remaining + + const srcBefore = await vUSDT.balanceOf(userAddr); + const dstBefore = await vUSDT.balanceOf(dstAddr); + await vUSDT.connect(user).transfer(dstAddr, transferAmount); + + expect(await vUSDT.balanceOf(userAddr)).to.equal(srcBefore.sub(transferAmount)); + expect(await vUSDT.balanceOf(dstAddr)).to.equal(dstBefore.add(transferAmount)); + }); + }); + + // ===================================================================== + // Part 3: Oracle Pump — DBO Activates Protection + // ===================================================================== + describe("3. Oracle Pump — DBO activates protection", () => { + let borrower: Signer; + + before(async () => { + borrower = (await ethers.getSigners())[3]; + const borrowerAddr = await borrower.getAddress(); + + resetPrices(); + + // Fund borrower with USDT + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(borrowerAddr, parseUnits("10000", 18)); + + // Supply USDT as collateral + const usdtBorrower = BEP20__factory.connect(USDT_ADDR, borrower); + await usdtBorrower.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(borrower).mint(parseUnits("10000", 18)); + await comptroller.connect(borrower).enterMarkets([vUSDT_ADDRESS]); + + // Borrow some BTC at normal prices + // 10000 USDT * $1 * CF=0.8 = $8000 capacity. 0.01 BTC * $60k = $600 + await vBTC.connect(borrower).borrow(parseUnits("0.01", 18)); + + pumpUSDTPrice(); // USDT $1 → $1.50 + }); + + it("borrow reverts — DBO bounds collateral at pre-pump price", async () => { + // At pumped $1.50: capacity = 10000 * 1.50 * 0.8 = $12000 → ~0.2 BTC + // At bounded $1 (window min): capacity = 10000 * 1 * 0.8 = $8000 → ~0.133 BTC + // Existing borrow: 0.01 BTC = $600. Try 0.15 BTC = $9000 total → exceeds bounded $8000 + await expect(vBTC.connect(borrower).borrow(parseUnits("0.15", 18))).to.be.revertedWith("math error"); + }); + + it("repayBorrow succeeds during pump", async () => { + const repayAmount = parseUnits("0.001", 18); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await borrower.getAddress(), repayAmount); + + const btcbBorrower = BEP20__factory.connect(BTCB_ADDR, borrower); + await btcbBorrower.approve(vBTC_ADDRESS, repayAmount); + + const borrowBefore = await vBTC.borrowBalanceStored(await borrower.getAddress()); + const uBalBefore = await btcbBorrower.balanceOf(await borrower.getAddress()); + await expect(vBTC.connect(borrower).repayBorrow(repayAmount)).to.emit(vBTC, "RepayBorrow"); + + expect(await vBTC.borrowBalanceStored(await borrower.getAddress())).to.be.closeTo( + borrowBefore.sub(repayAmount), + parseUnits("0.000001", 18), + ); + expect(await btcbBorrower.balanceOf(await borrower.getAddress())).to.equal(uBalBefore.sub(repayAmount)); + }); + + it("liquidation NOT triggered — borrower solvent at spot LT", async () => { + const liquidator = (await ethers.getSigners())[4]; + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.01", 18)); + + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.01", 18)); + + // LT path: 10000 * $1.50 * LT=0.9 = $13500 >> 0.01 BTC * $60k = $600 + await expect( + vBTC + .connect(liquidator) + .liquidateBorrow(await borrower.getAddress(), parseUnits("0.005", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); // INSUFFICIENT_SHORTFALL + }); + + it("borrow succeeds within bounded capacity despite pump", async () => { + // At bounded $1: capacity = 10000 * 1 * 0.8 = $8000. 0.001 BTC * $60k = $60 → within capacity + const borrowAmt = parseUnits("0.001", 18); + const btcbBorrower = BEP20__factory.connect(BTCB_ADDR, borrower); + const uBalBefore = await btcbBorrower.balanceOf(await borrower.getAddress()); + const borrowBefore = await vBTC.borrowBalanceStored(await borrower.getAddress()); + + await expect(vBTC.connect(borrower).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + + expect(await btcbBorrower.balanceOf(await borrower.getAddress())).to.equal(uBalBefore.add(borrowAmt)); + expect(await vBTC.borrowBalanceStored(await borrower.getAddress())).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + + it("redeem reverts — bounded prices limit withdrawal", async () => { + // Borrow more to make position tight at bounded capacity + // Existing: 0.01 BTC. Borrow additional to approach bounded limit + await vBTC.connect(borrower).borrow(parseUnits("0.10", 18)); + // Now ~0.12 BTC = $7200 vs bounded capacity $8000 → tight + // Redeem 3000 USDT → 7000 remaining → capacity = 7000 * $1 * 0.8 = $5600 < $7200 → shortfall + await expect(vUSDT.connect(borrower).redeemUnderlying(parseUnits("3000", 18))).to.be.revertedWith( + "math error", + ); + }); + + it("transfer blocked when bounded prices show shortfall", async () => { + // Transfer large vUSDT → would reduce collateral below bounded capacity → Failure + const dst = (await ethers.getSigners())[4]; + await expect(vUSDT.connect(borrower).transfer(await dst.getAddress(), parseUnits("5000", 18))).to.emit( + vUSDT, + "Failure", + ); + }); + }); + + // ===================================================================== + // Part 4: Oracle Crash — DBO Inflates Debt + // ===================================================================== + describe("4. Oracle Crash — DBO inflates debt value", () => { + let borrower2: Signer; + + before(async () => { + borrower2 = (await ethers.getSigners())[5]; + const addr = await borrower2.getAddress(); + + resetPrices(); + + // Fund and set up position + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("50000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower2); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("50000", 18)); + await vUSDT.connect(borrower2).mint(parseUnits("50000", 18)); + await comptroller.connect(borrower2).enterMarkets([vUSDT_ADDRESS]); + + // Borrow near max capacity: 50000 * $1 * 0.8 = $40000 → 40000/60000 = 0.6667 BTC + // Borrow 98%: ~0.653 BTC + const [, borrowCapacity] = await comptroller.getBorrowingPower(addr); + const maxBtcBorrow = borrowCapacity.mul(parseUnits("1", 18)).div(BTCB_PRICE).mul(98).div(100); + + await vBTC.connect(borrower2).borrow(maxBtcBorrow); + + crashBTCBPrice(); // BTC $60k → $42k + }); + + it("borrow reverts after BTC price crash — DBO inflates debt", async () => { + // DBO bounds debt at window max ($60k) → existing debt stays high + // User at 98% capacity with bounded $60k debt → any additional borrow fails + const [, remainingCapacity] = await comptroller.getBorrowingPower(await borrower2.getAddress()); + const borrowAttempt = remainingCapacity.mul(parseUnits("1", 18)).div(BTCB_PRICE).mul(2); + + await expect(vBTC.connect(borrower2).borrow(borrowAttempt)).to.be.revertedWith("math error"); + }); + + it("repayBorrow works during crash", async () => { + const repayAmount = parseUnits("0.001", 18); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await borrower2.getAddress(), repayAmount); + + const btcbUser = BEP20__factory.connect(BTCB_ADDR, borrower2); + await btcbUser.approve(vBTC_ADDRESS, repayAmount); + + const borrowBefore = await vBTC.borrowBalanceStored(await borrower2.getAddress()); + const uBalBefore = await btcbUser.balanceOf(await borrower2.getAddress()); + await expect(vBTC.connect(borrower2).repayBorrow(repayAmount)).to.emit(vBTC, "RepayBorrow"); + + expect(await vBTC.borrowBalanceStored(await borrower2.getAddress())).to.be.closeTo( + borrowBefore.sub(repayAmount), + parseUnits("0.000001", 18), + ); + expect(await btcbUser.balanceOf(await borrower2.getAddress())).to.equal(uBalBefore.sub(repayAmount)); + }); + }); + + // ===================================================================== + // Part 5: CF vs LT Path Divergence + // ===================================================================== + describe("5. CF vs LT path divergence", () => { + let borrower3: Signer; + + before(async () => { + borrower3 = (await ethers.getSigners())[6]; + const addr = await borrower3.getAddress(); + + resetPrices(); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower3); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(borrower3).mint(parseUnits("10000", 18)); + await comptroller.connect(borrower3).enterMarkets([vUSDT_ADDRESS]); + await vBTC.connect(borrower3).borrow(parseUnits("0.01", 18)); + + pumpUSDTPrice(); + }); + + it("borrow blocked (CF bounded) but liquidation rejected (LT spot solvent)", async () => { + // CF bounded: capacity = 10000 * $1 * 0.8 = $8000. 0.15 BTC * $60k = $9000 > $8000 + await expect(vBTC.connect(borrower3).borrow(parseUnits("0.15", 18))).to.be.revertedWith("math error"); + + // LT spot pumped: 10000 * $1.50 * 0.9 = $13500 >> 0.01 BTC * $60k = $600 + const liquidator = (await ethers.getSigners())[7]; + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.01", 18)); + + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.01", 18)); + + await expect( + vBTC + .connect(liquidator) + .liquidateBorrow(await borrower3.getAddress(), parseUnits("0.005", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); + }); + + it("getBorrowingPower (CF) shows less capacity than getAccountLiquidity (LT)", async () => { + const addr = await borrower3.getAddress(); + const [, cfLiquidity] = await comptroller.getBorrowingPower(addr); + const [, ltLiquidity] = await comptroller.getAccountLiquidity(addr); + + // LT uses pumped $1.50 spot → higher collateral. CF uses bounded $1 → lower + expect(ltLiquidity).to.be.gt(cfLiquidity); + }); + + it("getBorrowingPower before vs after pump — bounded prices cap capacity", async () => { + // Set up fresh user to get clean before/after comparison + const freshUser = (await ethers.getSigners())[8]; + const freshAddr = await freshUser.getAddress(); + + resetPrices(); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(freshAddr, parseUnits("10000", 18)); + const usdtFresh = BEP20__factory.connect(USDT_ADDR, freshUser); + await usdtFresh.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(freshUser).mint(parseUnits("10000", 18)); + await comptroller.connect(freshUser).enterMarkets([vUSDT_ADDRESS]); + + // Before pump: record borrowing power at $1 + const [, liquidityBefore] = await comptroller.getBorrowingPower(freshAddr); + + // Pump USDT to $1.50 + pumpUSDTPrice(); + + // After pump: DBO bounds collateral at window min ($1) → capacity stays same + const [, liquidityAfter] = await comptroller.getBorrowingPower(freshAddr); + + // Borrowing power unchanged — DBO capped at pre-pump price + expect(liquidityAfter).to.equal(liquidityBefore); + + // But LT uses pumped spot → higher value + const [, ltLiquidity] = await comptroller.getAccountLiquidity(freshAddr); + expect(ltLiquidity).to.be.gt(liquidityAfter); + }); + }); + + // ===================================================================== + // Part 6: Attack Scenarios + // ===================================================================== + describe("6. Attack scenarios", () => { + beforeEach(async () => { + resetPrices(); + }); + + it("pump-and-borrow attack blocked by DBO", async () => { + const attacker = (await ethers.getSigners())[8]; + const addr = await attacker.getAddress(); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("10000", 18)); + + const usdtAttacker = BEP20__factory.connect(USDT_ADDR, attacker); + await usdtAttacker.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(attacker).mint(parseUnits("10000", 18)); + await comptroller.connect(attacker).enterMarkets([vUSDT_ADDRESS]); + + // Small borrow at normal prices works: 0.001 BTC = $60 + const smallBorrow = parseUnits("0.001", 18); + const btcbAttacker = BEP20__factory.connect(BTCB_ADDR, attacker); + const uBalBefore = await btcbAttacker.balanceOf(addr); + const borrowBefore = await vBTC.borrowBalanceStored(addr); + await expect(vBTC.connect(attacker).borrow(smallBorrow)).to.emit(vBTC, "Borrow"); + expect(await btcbAttacker.balanceOf(addr)).to.equal(uBalBefore.add(smallBorrow)); + expect(await vBTC.borrowBalanceStored(addr)).to.be.closeTo( + borrowBefore.add(smallBorrow), + parseUnits("0.000001", 18), + ); + + // Pump USDT 5x: $1 → $5 + const pumpedPrice5x = parseUnits("5", 18); + fakeOracle.getPrice.whenCalledWith(USDT_ADDR).returns(pumpedPrice5x); + fakeOracle.getUnderlyingPrice.whenCalledWith(vUSDT_ADDRESS).returns(pumpedPrice5x); + + // At pumped $5: capacity = 10000 * 5 * 0.8 = $40000 → 0.66 BTC + // At bounded $1: capacity = $8000 → 0.133 BTC. Try 0.5 BTC = $30000 → blocked + await expect(vBTC.connect(attacker).borrow(parseUnits("0.5", 18))).to.be.revertedWith("math error"); + }); + }); + + // ===================================================================== + // Part 7: Protection Active at Normal Prices + // ===================================================================== + describe("7. Protection active but prices normal — bounded pricing restricts", () => { + let borrower4: Signer; + + before(async () => { + borrower4 = (await ethers.getSigners())[9]; + const addr = await borrower4.getAddress(); + + resetPrices(); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower4); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(borrower4).mint(parseUnits("10000", 18)); + await comptroller.connect(borrower4).enterMarkets([vUSDT_ADDRESS]); + + // Borrow at normal prices + await vBTC.connect(borrower4).borrow(parseUnits("0.01", 18)); + + // Pump to trigger protection + pumpUSDTPrice(); + + // Trigger state update + await dbo.connect(timelock).updateProtectionState(vUSDT_ADDRESS); + + // Return price to normal — but protection remains active (cooldown not elapsed) + resetPrices(); + }); + + it("protection still active despite normal prices — bounded collateral restricts borrow", async () => { + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + }); + + it("liquidation uses spot (normal) prices — borrower solvent", async () => { + const liquidator = (await ethers.getSigners())[10]; + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.01", 18)); + + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.01", 18)); + + // At normal $1 spot + LT, borrower is solvent + await expect( + vBTC + .connect(liquidator) + .liquidateBorrow(await borrower4.getAddress(), parseUnits("0.005", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); // INSUFFICIENT_SHORTFALL + }); + }); + + // ===================================================================== + // Part 8: Keeper Disables Protection + // ===================================================================== + describe("8. Keeper disables protection — normal operation resumes", () => { + it("disableActiveProtectedPrice reverts before cooldown elapses", async () => { + await dbo.assetProtectionConfig(USDT_ADDR); + await expect(dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR)).to.be.reverted; + }); + + it("keeper narrows window + disables protection after cooldown", async () => { + // Advance time past cooldown + await time.increase(COOLDOWN_PERIOD + 1); + + // Narrow window: max just above spot, min just below spot (2% range < 5% threshold) + const newMax = USDT_PRICE.mul(101).div(100); // $1.01 + const newMin = USDT_PRICE.mul(99).div(100); // $0.99 + + // Order: first narrow max down, then narrow min up + await dbo.connect(timelock).updateMaxPrice(USDT_ADDR, newMax); + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, newMin); + + // Disable protection + await expect(dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR)).to.not.be.reverted; + + const updatedConfig = await dbo.assetProtectionConfig(USDT_ADDR); + expect(updatedConfig.currentlyUsingProtectedPrice).to.be.false; + }); + }); + + // ===================================================================== + // Part 9: enterPool with DBO + // ===================================================================== + describe("9. enterPool with DBO", () => { + it("enterPool succeeds with no borrows regardless of DBO state", async () => { + const newUser = (await ethers.getSigners())[11]; + const addr = await newUser.getAddress(); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("100", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, newUser); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("100", 18)); + await vUSDT.connect(newUser).mint(parseUnits("100", 18)); + await comptroller.connect(newUser).enterMarkets([vUSDT_ADDRESS]); + + const [err, , shortfall] = await comptroller.getAccountLiquidity(addr); + expect(err).to.equal(0); + expect(shortfall).to.equal(0); + }); + }); + + // ===================================================================== + // Part 10: exitMarket with DBO + // ===================================================================== + describe("10. exitMarket with DBO", () => { + it("exitMarket succeeds with no borrows", async () => { + const newUser = (await ethers.getSigners())[12]; + const addr = await newUser.getAddress(); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("100", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, newUser); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("100", 18)); + await vUSDT.connect(newUser).mint(parseUnits("100", 18)); + await comptroller.connect(newUser).enterMarkets([vUSDT_ADDRESS]); + + const errCode = await comptroller.connect(newUser).callStatic.exitMarket(vUSDT_ADDRESS); + expect(errCode).to.equal(0); + }); + + it("exitMarket blocked at bounded CF but solvent at spot LT", async () => { + const exitUser = ethers.Wallet.createRandom().connect(ethers.provider); + const exitAddr = await exitUser.getAddress(); + await setBalance(exitAddr, parseUnits("10", 18)); + + await neutralizeDBO(); + + // Supply and borrow near max + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(exitAddr, parseUnits("10000", 18)); + const usdtExit = BEP20__factory.connect(USDT_ADDR, exitUser); + await usdtExit.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(exitUser).mint(parseUnits("10000", 18)); + await comptroller.connect(exitUser).enterMarkets([vUSDT_ADDRESS]); + await vBTC.connect(exitUser).borrow(parseUnits("0.01", 18)); + + // Pump triggers DBO protection → bounded collateral at $1 + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + + // exitMarket blocked at CF (bounded prices create shortfall on full exit) + const exitErrCode = await comptroller.connect(exitUser).callStatic.exitMarket(vUSDT_ADDRESS); + expect(exitErrCode).to.not.equal(0); + + // But account solvent at LT (spot $1.50 → plenty of headroom) + const [ltErr, ltLiquidity, ltShortfall] = await comptroller.getAccountLiquidity(exitAddr); + expect(ltErr).to.equal(0); + expect(ltLiquidity).to.be.gt(0); + expect(ltShortfall).to.equal(0); + }); + }); + + // ===================================================================== + // Part 11: Existing Position Preservation + // ===================================================================== + describe("11. Existing positions after upgrade", () => { + it("user with existing borrows — account liquidity consistent", async () => { + const [err] = await comptroller.getAccountLiquidity(USER_WITH_POSITIONS); + expect(err).to.equal(0); + }); + + it("view functions return consistent results for existing accounts", async () => { + const [cfErr] = await comptroller.getBorrowingPower(USER_WITH_POSITIONS); + const [ltErr] = await comptroller.getAccountLiquidity(USER_WITH_POSITIONS); + expect(cfErr).to.equal(0); + expect(ltErr).to.equal(0); + }); + }); + + // ===================================================================== + // Part 12: Edge Cases + // ===================================================================== + describe("12. Edge cases", () => { + it("DBO returns same price as spot when no deviation — borrow succeeds normally", async () => { + resetPrices(); + + const newUser = (await ethers.getSigners())[13]; + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(await newUser.getAddress(), parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, newUser); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(newUser).mint(parseUnits("10000", 18)); + await comptroller.connect(newUser).enterMarkets([vUSDT_ADDRESS]); + + // 10000 USDT * $1 * 0.8 = $8000 capacity. 0.001 BTC * $60k = $60 → easy + const borrowAmt = parseUnits("0.001", 18); + const btcbNewUser = BEP20__factory.connect(BTCB_ADDR, newUser); + const uBalBefore = await btcbNewUser.balanceOf(await newUser.getAddress()); + const borrowBefore = await vBTC.borrowBalanceStored(await newUser.getAddress()); + await expect(vBTC.connect(newUser).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + expect(await btcbNewUser.balanceOf(await newUser.getAddress())).to.equal(uBalBefore.add(borrowAmt)); + expect(await vBTC.borrowBalanceStored(await newUser.getAddress())).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + }); + + // ===================================================================== + // Part 13: Keeper Updates Min/Max Price During Protection + // ===================================================================== + describe("13. Keeper updates min/max price during protection — user action effects", () => { + let borrower5: Signer; + + before(async () => { + borrower5 = (await ethers.getSigners())[14]; + const addr = await borrower5.getAddress(); + + await neutralizeDBO(); + + // Supply 10000 USDT as collateral + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower5); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(borrower5).mint(parseUnits("10000", 18)); + await comptroller.connect(borrower5).enterMarkets([vUSDT_ADDRESS]); + + // Pump USDT to $1.50 and trigger protection + pumpUSDTPrice(); + + // Borrow 0.10 BTC = $6000 (within bounded $8000 capacity: 10000 * $1 * 0.8) + await vBTC.connect(borrower5).borrow(parseUnits("0.10", 18)); + + // Verify protection is active + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + }); + + describe("13a. Before keeper action — user restricted at bounded prices", () => { + it("borrow 0.05 BTC more reverts — exceeds bounded capacity", async () => { + // Existing: 0.10 BTC=$6000. New: 0.05 BTC=$3000. Total=$9000 > $8000 → revert + await expect(vBTC.connect(borrower5).borrow(parseUnits("0.05", 18))).to.be.revertedWith("math error"); + }); + + it("redeem 3000 USDT reverts — remaining collateral insufficient", async () => { + // Remaining 7000 USDT * $1 (bounded) * 0.8 = $5600 < $6000 debt → shortfall + await expect(vUSDT.connect(borrower5).redeemUnderlying(parseUnits("3000", 18))).to.be.revertedWith( + "math error", + ); + }); + + it("transfer 3000 vUSDT reverts — same as redeem", async () => { + const dst = (await ethers.getSigners())[17]; + await expect(vUSDT.connect(borrower5).transfer(await dst.getAddress(), parseUnits("3000", 18))).to.emit( + vUSDT, + "Failure", + ); + }); + }); + + describe("13b. Keeper raises minPrice → collateral valuation increases", () => { + before(async () => { + // Keeper raises min from $1 to $1.30 (valid: $1.30 < max=$1.50 && $1.30 <= spot=$1.50) + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, parseUnits("1.30", 18)); + // Bounded collateral = min($1.50, $1.30) = $1.30 + // New capacity = 10000 * $1.30 * 0.8 = $10,400 + }); + + it("borrow 0.05 BTC now succeeds — increased collateral valuation", async () => { + // Total debt = 0.15 BTC * $60k = $9000 < $10,400 → OK + const borrowAmt = parseUnits("0.05", 18); + const btcb5 = BEP20__factory.connect(BTCB_ADDR, borrower5); + const uBalBefore = await btcb5.balanceOf(await borrower5.getAddress()); + const borrowBefore = await vBTC.borrowBalanceStored(await borrower5.getAddress()); + await expect(vBTC.connect(borrower5).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + expect(await btcb5.balanceOf(await borrower5.getAddress())).to.equal(uBalBefore.add(borrowAmt)); + expect(await vBTC.borrowBalanceStored(await borrower5.getAddress())).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + + it("getBorrowingPower reflects higher capacity than before keeper action", async () => { + const [err, liquidity, shortfall] = await comptroller.getBorrowingPower(await borrower5.getAddress()); + expect(err).to.equal(0); + // Should have remaining liquidity (capacity $10400 - debt ~$9000 = $1400) + expect(liquidity).to.be.gt(0); + expect(shortfall).to.equal(0); + }); + + it("liquidation still uses spot LT — unaffected by keeper min update", async () => { + const liquidator = (await ethers.getSigners())[17]; + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.1", 18)); + + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.1", 18)); + + // LT spot: 10000 * $1.50 * 0.9 = $13,500 >> debt ~$9000 → solvent + await expect( + vBTC + .connect(liquidator) + .liquidateBorrow(await borrower5.getAddress(), parseUnits("0.05", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); // INSUFFICIENT_SHORTFALL + }); + }); + + describe("13c. Keeper lowers BTC maxPrice → debt valuation decreases", () => { + let borrower5c: Signer; + + before(async () => { + borrower5c = (await ethers.getSigners())[15]; + const addr = await borrower5c.getAddress(); + + resetPrices(); + + // Supply 10000 USDT + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower5c); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(borrower5c).mint(parseUnits("10000", 18)); + await comptroller.connect(borrower5c).enterMarkets([vUSDT_ADDRESS]); + + // Borrow 0.12 BTC at normal $60k = $7200 (near $8000 capacity) + await vBTC.connect(borrower5c).borrow(parseUnits("0.12", 18)); + + // Pump BTC from $60k to $90k → trigger BTC protection + pumpBTCBPrice(); + + // Trigger state update: call DBO updateProtectionState directly for BTC + // This is what _updateProtectionStates does internally for each market + await dbo.connect(timelock).updateProtectionState(vBTC_ADDRESS); + + // Verify BTC protection activated + const btcConfig = await dbo.assetProtectionConfig(BTCB_ADDR); + expect(btcConfig.currentlyUsingProtectedPrice).to.be.true; + + // Return BTC spot to $60k — window: min=$60k, max=$90k + fakeOracle.getPrice.whenCalledWith(BTCB_ADDR).returns(BTCB_PRICE); + fakeOracle.getUnderlyingPrice.whenCalledWith(vBTC_ADDRESS).returns(BTCB_PRICE); + // Bounded debt = max($60k, $90k) = $90k → 0.12 BTC valued at $10,800 (was $7,200) + }); + + it("borrow blocked — BTC debt inflated at bounded max", async () => { + // Verify BTC protection is active and window expanded + const btcCfg = await dbo.assetProtectionConfig(BTCB_ADDR); + expect(btcCfg.currentlyUsingProtectedPrice).to.be.true; + expect(btcCfg.maxPrice.gte(BTCB_PUMPED)).to.be.true; + + // With protection: debt = max(spot=$60k, max=$90k) = $90k + // 0.12 BTC * $90k = $10,800. Capacity ≈ $8000 → shortfall + const [, , shortfall] = await comptroller.getBorrowingPower(await borrower5c.getAddress()); + expect(shortfall).to.be.gt(0); + await expect(vBTC.connect(borrower5c).borrow(parseUnits("0.001", 18))).to.be.revertedWith("math error"); + }); + + it("keeper lowers BTC maxPrice to $65k → borrow succeeds", async () => { + // Keeper: max $90k → $65k (valid: $65k > min=$60k && $65k >= spot=$60k) + await dbo.connect(timelock).updateMaxPrice(BTCB_ADDR, parseUnits("65000", 18)); + // Bounded debt = max($60k, $65k) = $65k → 0.12 BTC = $7800 + // Capacity $8000 - $7800 = $200 headroom → very small borrow works + const borrowAmt = parseUnits("0.001", 18); + const btcb5c = BEP20__factory.connect(BTCB_ADDR, borrower5c); + const uBalBefore = await btcb5c.balanceOf(await borrower5c.getAddress()); + await vBTC.borrowBalanceStored(await borrower5c.getAddress()); + await expect(vBTC.connect(borrower5c).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + expect(await btcb5c.balanceOf(await borrower5c.getAddress())).to.equal(uBalBefore.add(borrowAmt)); + }); + }); + }); + + // ===================================================================== + // Part 14: Keeper Updates Threshold Near Price Bound + // ===================================================================== + describe("14. Keeper updates threshold near price bound — user action effects", () => { + describe("14a. Lowering trigger threshold activates protection → restricts user", () => { + let borrower6: Signer; + + before(async () => { + borrower6 = (await ethers.getSigners())[17]; + const addr = await borrower6.getAddress(); + + await neutralizeDBO(); + + // Supply 10000 USDT, enter market + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower6); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(borrower6).mint(parseUnits("10000", 18)); + await comptroller.connect(borrower6).enterMarkets([vUSDT_ADDRESS]); + + // Borrow 98% of capacity at $1 + const [, capacity] = await comptroller.getBorrowingPower(addr); + const targetBorrow = capacity.mul(98).div(100).mul(parseUnits("1", 18)).div(BTCB_PRICE); + await vBTC.connect(borrower6).borrow(targetBorrow); + + // Mild pump: $1 → $1.12 (12% < 16.67% trigger — protection stays inactive) + const mildPrice = parseUnits("1.12", 18); + fakeOracle.getPrice.whenCalledWith(USDT_ADDR).returns(mildPrice); + fakeOracle.getUnderlyingPrice.whenCalledWith(vUSDT_ADDRESS).returns(mildPrice); + + // Expand window but do NOT trigger protection (12% < 16.67%) + await dbo.updateProtectionState(vUSDT_ADDRESS); + }); + + it("before threshold change — protection is NOT active", async () => { + const config = await dbo.assetProtectionConfig(USDT_ADDR); + // 12% deviation < 16.67% trigger → protection should not be active + expect(config.currentlyUsingProtectedPrice).to.be.false; + }); + + it("before threshold change — borrow succeeds at spot price", async () => { + // Not protected → bounded = spot. Small additional borrow should succeed + const borrowAmt = parseUnits("0.01", 18); + const btcb6 = BEP20__factory.connect(BTCB_ADDR, borrower6); + const uBalBefore = await btcb6.balanceOf(await borrower6.getAddress()); + const borrowBefore = await vBTC.borrowBalanceStored(await borrower6.getAddress()); + await expect(vBTC.connect(borrower6).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + expect(await btcb6.balanceOf(await borrower6.getAddress())).to.equal(uBalBefore.add(borrowAmt)); + expect(await vBTC.borrowBalanceStored(await borrower6.getAddress())).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + + it("keeper lowers trigger to 10% — protection activates, borrow reverts", async () => { + // Lower trigger from 16.67% to 10% (reset from 5% to 3%) + await dbo.connect(timelock).setThresholds(USDT_ADDR, parseUnits("0.10", 18), parseUnits("0.03", 18)); + + // Now 12% deviation > 10% trigger → next state-changing CF-path call triggers protection + // borrow → borrowAllowed → _updateProtectionStates → _checkAndTriggerProtection + // After trigger: bounded collateral = min(spot, windowMin) = windowMin (lower) + // Capacity drops → additional borrow that was fine before now fails + // Try to borrow a meaningful amount relative to remaining capacity + const [, remaining] = await comptroller.getBorrowingPower(await borrower6.getAddress()); + // Borrow 2x remaining capacity (if any) to ensure it exceeds bounded limit after trigger + const attemptBtc = remaining.mul(2).mul(parseUnits("1", 18)).div(BTCB_PRICE); + await expect(vBTC.connect(borrower6).borrow(attemptBtc)).to.be.revertedWith("math error"); + }); + + it("redeem also blocked after threshold lowering triggers protection", async () => { + await expect(vUSDT.connect(borrower6).redeemUnderlying(parseUnits("100", 18))).to.be.revertedWith( + "math error", + ); + }); + + it("liquidation unaffected — still uses spot LT", async () => { + // LT uses spot (mildPrice) → user has enough collateral at spot LT + const liquidator = (await ethers.getSigners())[18]; + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.1", 18)); + + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.1", 18)); + + await expect( + vBTC + .connect(liquidator) + .liquidateBorrow(await borrower6.getAddress(), parseUnits("0.05", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); // INSUFFICIENT_SHORTFALL + }); + }); + + describe("14b. Raising trigger threshold — does NOT retroactively disable protection", () => { + let borrower7: Signer; + + before(async () => { + borrower7 = (await ethers.getSigners())[18]; + const addr = await borrower7.getAddress(); + + await neutralizeDBO(); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower7); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(borrower7).mint(parseUnits("10000", 18)); + await comptroller.connect(borrower7).enterMarkets([vUSDT_ADDRESS]); + + // Borrow at normal prices + await vBTC.connect(borrower7).borrow(parseUnits("0.10", 18)); + + // Pump to $1.50 and trigger protection deterministically + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + }); + + it("protection is active", async () => { + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + }); + + it("keeper raises trigger to 25% — protection stays active (not retroactive)", async () => { + await dbo.connect(timelock).setThresholds(USDT_ADDR, parseUnits("0.25", 18), parseUnits("0.08", 18)); + + // Protection already triggered → changing threshold doesn't auto-disable + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + + // User still restricted at bounded prices + await expect(vBTC.connect(borrower7).borrow(parseUnits("0.05", 18))).to.be.revertedWith("math error"); + }); + + it("but wider reset threshold makes disableActiveProtectedPrice easier", async () => { + // Advance past cooldown + await time.increase(COOLDOWN_PERIOD + 1); + + // Narrow window close to spot + await dbo.connect(timelock).updateMaxPrice(USDT_ADDR, USDT_PUMPED.mul(101).div(100)); + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, USDT_PUMPED.mul(95).div(100)); + // Range = ($1.515 - $1.425) / $1.425 ≈ 6.3% + // With reset=8%, 6.3% < 8% → disableActiveProtectedPrice should succeed + await expect(dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR)).to.not.be.reverted; + + // User can now borrow at spot capacity + const borrowAmt = parseUnits("0.05", 18); + const btcb7 = BEP20__factory.connect(BTCB_ADDR, borrower7); + const uBalBefore = await btcb7.balanceOf(await borrower7.getAddress()); + const borrowBefore = await vBTC.borrowBalanceStored(await borrower7.getAddress()); + await expect(vBTC.connect(borrower7).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + expect(await btcb7.balanceOf(await borrower7.getAddress())).to.equal(uBalBefore.add(borrowAmt)); + expect(await vBTC.borrowBalanceStored(await borrower7.getAddress())).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + }); + + describe("14c. setCooldownPeriod affects when protection can be disabled", () => { + let borrower8: Signer; + + before(async () => { + borrower8 = (await ethers.getSigners())[19]; + const addr = await borrower8.getAddress(); + + await neutralizeDBO(); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower8); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(borrower8).mint(parseUnits("10000", 18)); + await comptroller.connect(borrower8).enterMarkets([vUSDT_ADDRESS]); + + await vBTC.connect(borrower8).borrow(parseUnits("0.10", 18)); + + // Pump to $1.50 and trigger protection deterministically + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + + // Verify protection is active + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + }); + + it("keeper extends cooldown — disableActiveProtectedPrice reverts after original cooldown", async () => { + // Extend cooldown from 1 hour to 2 hours + await dbo.connect(timelock).setCooldownPeriod(USDT_ADDR, COOLDOWN_PERIOD * 2); + + // Advance past original 1 hour cooldown but NOT the new 2-hour cooldown + await time.increase(COOLDOWN_PERIOD + 1); + + // Narrow window: spot=$1.50 (pumped), window=[$1, $1.50] + const newMax = USDT_PUMPED.mul(101).div(100); // $1.515 + const newMin = USDT_PUMPED.mul(99).div(100); // $1.485 + await dbo.connect(timelock).updateMaxPrice(USDT_ADDR, newMax); + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, newMin); + + // Still within new 2-hour cooldown → revert + await expect(dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR)).to.be.reverted; + }); + + it("after extended cooldown elapses — disableActiveProtectedPrice succeeds", async () => { + // Advance past remaining cooldown + await time.increase(COOLDOWN_PERIOD + 1); + + await expect(dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR)).to.not.be.reverted; + + // User can now borrow + const borrowAmt = parseUnits("0.05", 18); + const btcb8 = BEP20__factory.connect(BTCB_ADDR, borrower8); + const uBalBefore = await btcb8.balanceOf(await borrower8.getAddress()); + const borrowBefore = await vBTC.borrowBalanceStored(await borrower8.getAddress()); + await expect(vBTC.connect(borrower8).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + expect(await btcb8.balanceOf(await borrower8.getAddress())).to.equal(uBalBefore.add(borrowAmt)); + expect(await vBTC.borrowBalanceStored(await borrower8.getAddress())).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + }); + }); + + // ===================================================================== + // Part 15: All User Actions — Protection Active (Pumped Prices) + // ===================================================================== + describe("15. All user actions — protection active (pumped prices)", () => { + let user15: Signer; + let user15Addr: string; + + before(async () => { + user15 = ethers.Wallet.createRandom().connect(ethers.provider); + user15Addr = await user15.getAddress(); + await setBalance(user15Addr, parseUnits("10", 18)); + + await neutralizeDBO(); + + // Supply 10000 USDT as collateral at normal $1 + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user15Addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, user15); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(user15).mint(parseUnits("10000", 18)); + await comptroller.connect(user15).enterMarkets([vUSDT_ADDRESS]); + + // Borrow 95% of capacity: capacity = 10000 * $1 * 0.8 = $8000 + // 95% = $7600 → 7600/60000 ≈ 0.1267 BTC + const [, capacity] = await comptroller.getBorrowingPower(user15Addr); + const borrowBtc = capacity.mul(95).div(100).mul(parseUnits("1", 18)).div(BTCB_PRICE); + await vBTC.connect(user15).borrow(borrowBtc); + + // Pump USDT to $1.50 → triggers DBO protection + pumpUSDTPrice(); + + // Trigger protection state update + await dbo.updateProtectionState(vUSDT_ADDRESS); + + // Verify protection is active + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + }); + + it("mint succeeds — no liquidity check", async () => { + const mintAmount = parseUnits("100", 18); + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user15Addr, mintAmount); + const usdtUser = BEP20__factory.connect(USDT_ADDR, user15); + await usdtUser.approve(vUSDT_ADDRESS, mintAmount); + + const vBalBefore = await vUSDT.balanceOf(user15Addr); + const uBalBefore = await usdtUser.balanceOf(user15Addr); + const er = await vUSDT.callStatic.exchangeRateCurrent(); + const expectedVTokens = mintAmount.mul(parseUnits("1", 18)).div(er); + await expect(vUSDT.connect(user15).mint(mintAmount)).to.emit(vUSDT, "Mint"); + + expect(await vUSDT.balanceOf(user15Addr)).to.be.closeTo(vBalBefore.add(expectedVTokens), parseUnits("1", 8)); + expect(await usdtUser.balanceOf(user15Addr)).to.equal(uBalBefore.sub(mintAmount)); + }); + + it("repayBorrow succeeds — no liquidity check", async () => { + const repayAmount = parseUnits("0.001", 18); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(user15Addr, repayAmount); + const btcbUser = BEP20__factory.connect(BTCB_ADDR, user15); + await btcbUser.approve(vBTC_ADDRESS, repayAmount); + + const borrowBefore = await vBTC.borrowBalanceStored(user15Addr); + const uBalBefore = await btcbUser.balanceOf(user15Addr); + await expect(vBTC.connect(user15).repayBorrow(repayAmount)).to.emit(vBTC, "RepayBorrow"); + + expect(await vBTC.borrowBalanceStored(user15Addr)).to.be.closeTo( + borrowBefore.sub(repayAmount), + parseUnits("0.000001", 18), + ); + expect(await btcbUser.balanceOf(user15Addr)).to.equal(uBalBefore.sub(repayAmount)); + }); + + it("borrow reverts — bounded collateral limits capacity", async () => { + // Bounded collateral = min($1.50, $1) = $1 → capacity = $8000 + // Already at 95% → only $400 headroom. Borrow $600 worth → revert + await expect(vBTC.connect(user15).borrow(parseUnits("0.01", 18))).to.be.revertedWith("math error"); + }); + + it("redeem reverts — removing collateral causes shortfall at bounded prices", async () => { + // Redeem 1000 USDT → 9000 remaining → capacity = 9000 * $1 * 0.8 = $7200 < ~$7600 debt + await expect(vUSDT.connect(user15).redeemUnderlying(parseUnits("1000", 18))).to.be.revertedWith("math error"); + }); + + it("transfer reverts — same CF path as redeem", async () => { + const dst = ethers.Wallet.createRandom().connect(ethers.provider); + await expect(vUSDT.connect(user15).transfer(await dst.getAddress(), parseUnits("1000", 18))).to.emit( + vUSDT, + "Failure", + ); + }); + + it("exitMarket reverts — removing all collateral causes shortfall", async () => { + const errCode = await comptroller.connect(user15).callStatic.exitMarket(vUSDT_ADDRESS); + expect(errCode).to.not.equal(0); // REJECTION + }); + + it("liquidateBorrow returns INSUFFICIENT_SHORTFALL — uses spot LT, borrower solvent", async () => { + // LT path: 10000 * $1.50 (pumped spot) * 0.9 = $13,500 >> ~$7600 debt → solvent + const liquidator = ethers.Wallet.createRandom().connect(ethers.provider); + await setBalance(await liquidator.getAddress(), parseUnits("10", 18)); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.1", 18)); + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.1", 18)); + + await expect( + vBTC.connect(liquidator).liquidateBorrow(user15Addr, parseUnits("0.05", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); // INSUFFICIENT_SHORTFALL + }); + + it("getAccountLiquidity shows solvency at spot LT prices", async () => { + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(user15Addr); + expect(err).to.equal(0); + expect(liquidity).to.be.gt(0); + expect(shortfall).to.equal(0); + }); + + it("claimVenus succeeds — CF path with updateProtectionState", async () => { + // claimVenus calls _getAccountLiquidity(USE_COLLATERAL_FACTOR) → _updateProtectionStates + // Should not revert regardless of protection state + await expect(comptroller.connect(user15)["claimVenus(address,address[])"](user15Addr, [vUSDT_ADDRESS])).to.not + .be.reverted; + }); + }); + + // ===================================================================== + // Part 16: All User Actions — Protection Active, Prices Normal (Stale) + // ===================================================================== + describe("16. All user actions — protection active, prices returned to normal", () => { + let user16: Signer; + let user16Addr: string; + + before(async () => { + user16 = ethers.Wallet.createRandom().connect(ethers.provider); + user16Addr = await user16.getAddress(); + await setBalance(user16Addr, parseUnits("10", 18)); + + await neutralizeDBO(); + + // Supply 10000 USDT at $1 + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user16Addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, user16); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(user16).mint(parseUnits("10000", 18)); + await comptroller.connect(user16).enterMarkets([vUSDT_ADDRESS]); + + // Borrow 95% of capacity + const [, capacity] = await comptroller.getBorrowingPower(user16Addr); + const borrowBtc = capacity.mul(95).div(100).mul(parseUnits("1", 18)).div(BTCB_PRICE); + await vBTC.connect(user16).borrow(borrowBtc); + + // Pump to trigger protection + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + + // Return prices to normal — but protection remains active (cooldown not elapsed) + resetPrices(); + + // Verify protection still active + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + }); + + it("mint succeeds — no liquidity check", async () => { + const mintAmount = parseUnits("100", 18); + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user16Addr, mintAmount); + const usdtUser = BEP20__factory.connect(USDT_ADDR, user16); + await usdtUser.approve(vUSDT_ADDRESS, mintAmount); + + const vBalBefore = await vUSDT.balanceOf(user16Addr); + const uBalBefore = await usdtUser.balanceOf(user16Addr); + const er = await vUSDT.callStatic.exchangeRateCurrent(); + const expectedVTokens = mintAmount.mul(parseUnits("1", 18)).div(er); + await expect(vUSDT.connect(user16).mint(mintAmount)).to.emit(vUSDT, "Mint"); + + expect(await vUSDT.balanceOf(user16Addr)).to.be.closeTo(vBalBefore.add(expectedVTokens), parseUnits("1", 8)); + expect(await usdtUser.balanceOf(user16Addr)).to.equal(uBalBefore.sub(mintAmount)); + }); + + it("repayBorrow succeeds — no liquidity check", async () => { + const repayAmount = parseUnits("0.001", 18); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(user16Addr, repayAmount); + const btcbUser = BEP20__factory.connect(BTCB_ADDR, user16); + await btcbUser.approve(vBTC_ADDRESS, repayAmount); + + const borrowBefore = await vBTC.borrowBalanceStored(user16Addr); + const uBalBefore = await btcbUser.balanceOf(user16Addr); + await expect(vBTC.connect(user16).repayBorrow(repayAmount)).to.emit(vBTC, "RepayBorrow"); + + expect(await vBTC.borrowBalanceStored(user16Addr)).to.be.closeTo( + borrowBefore.sub(repayAmount), + parseUnits("0.000001", 18), + ); + expect(await btcbUser.balanceOf(user16Addr)).to.equal(uBalBefore.sub(repayAmount)); + }); + + it("borrow restricted — bounded window limits capacity despite normal spot", async () => { + await expect(vBTC.connect(user16).borrow(parseUnits("0.01", 18))).to.be.revertedWith("math error"); + }); + + it("redeem restricted — bounded prices keep position conservative", async () => { + await expect(vUSDT.connect(user16).redeemUnderlying(parseUnits("1000", 18))).to.be.revertedWith("math error"); + }); + + it("transfer restricted — same CF path as redeem", async () => { + const dst = ethers.Wallet.createRandom().connect(ethers.provider); + await expect(vUSDT.connect(user16).transfer(await dst.getAddress(), parseUnits("1000", 18))).to.emit( + vUSDT, + "Failure", + ); + }); + + it("exitMarket restricted — bounded prices create shortfall on exit", async () => { + const errCode = await comptroller.connect(user16).callStatic.exitMarket(vUSDT_ADDRESS); + expect(errCode).to.not.equal(0); + }); + + it("liquidateBorrow returns INSUFFICIENT_SHORTFALL — spot prices normal, borrower solvent", async () => { + // LT path: 10000 * $1 * 0.9 = $9000 > ~$7600 debt → solvent + const liquidator = ethers.Wallet.createRandom().connect(ethers.provider); + await setBalance(await liquidator.getAddress(), parseUnits("10", 18)); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.1", 18)); + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.1", 18)); + + await expect( + vBTC.connect(liquidator).liquidateBorrow(user16Addr, parseUnits("0.05", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); + }); + + it("getBorrowingPower shows reduced capacity vs spot", async () => { + const [, cfLiquidity] = await comptroller.getBorrowingPower(user16Addr); + const [, ltLiquidity] = await comptroller.getAccountLiquidity(user16Addr); + // CF uses bounded prices, LT uses spot + // At normal prices: LT should >= CF (LT has higher weighting factor) + expect(ltLiquidity).to.be.gte(cfLiquidity); + }); + + it("getAccountLiquidity shows solvency at spot LT", async () => { + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(user16Addr); + expect(err).to.equal(0); + expect(liquidity).to.be.gt(0); + expect(shortfall).to.equal(0); + }); + + it("claimVenus succeeds — CF path with updateProtectionState", async () => { + await expect(comptroller.connect(user16)["claimVenus(address,address[])"](user16Addr, [vUSDT_ADDRESS])).to.not + .be.reverted; + }); + }); + + // ===================================================================== + // Part 17: All User Actions — After Keeper Disables Protection + // ===================================================================== + describe("17. All user actions — after keeper disables protection", () => { + let user17: Signer; + let user17Addr: string; + + before(async () => { + user17 = ethers.Wallet.createRandom().connect(ethers.provider); + user17Addr = await user17.getAddress(); + await setBalance(user17Addr, parseUnits("10", 18)); + + await neutralizeDBO(); + + // Supply 10000 USDT at $1 + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user17Addr, parseUnits("10000", 18)); + + const usdtUser = BEP20__factory.connect(USDT_ADDR, user17); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(user17).mint(parseUnits("10000", 18)); + await comptroller.connect(user17).enterMarkets([vUSDT_ADDRESS]); + + // Borrow small amount (leave plenty of headroom for post-disable tests) + await vBTC.connect(user17).borrow(parseUnits("0.05", 18)); // $3000 of $8000 capacity + + // Trigger protection, then disable it deterministically + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + resetPrices(); // return to $1 + + // Advance past cooldown and disable protection + // Window is deterministically [$0.99, $1.50] after pump (min from neutralize, max expanded) + await time.increase(COOLDOWN_PERIOD + 1); + await dbo.connect(timelock).updateMaxPrice(USDT_ADDR, USDT_PRICE.mul(101).div(100)); // $1.01 + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, USDT_PRICE.mul(99).div(100)); // $0.99 + await dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR); + + // Verify protection is disabled + const cfgAfter = await dbo.assetProtectionConfig(USDT_ADDR); + expect(cfgAfter.currentlyUsingProtectedPrice).to.be.false; + }); + + it("mint succeeds", async () => { + const mintAmount = parseUnits("100", 18); + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user17Addr, mintAmount); + const usdtUser = BEP20__factory.connect(USDT_ADDR, user17); + await usdtUser.approve(vUSDT_ADDRESS, mintAmount); + + const vBalBefore = await vUSDT.balanceOf(user17Addr); + const uBalBefore = await usdtUser.balanceOf(user17Addr); + const er = await vUSDT.callStatic.exchangeRateCurrent(); + const expectedVTokens = mintAmount.mul(parseUnits("1", 18)).div(er); + await expect(vUSDT.connect(user17).mint(mintAmount)).to.emit(vUSDT, "Mint"); + + expect(await vUSDT.balanceOf(user17Addr)).to.be.closeTo(vBalBefore.add(expectedVTokens), parseUnits("1", 8)); + expect(await usdtUser.balanceOf(user17Addr)).to.equal(uBalBefore.sub(mintAmount)); + }); + + it("repayBorrow succeeds", async () => { + const repayAmount = parseUnits("0.001", 18); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(user17Addr, repayAmount); + const btcbUser = BEP20__factory.connect(BTCB_ADDR, user17); + await btcbUser.approve(vBTC_ADDRESS, repayAmount); + + const borrowBefore = await vBTC.borrowBalanceStored(user17Addr); + const uBalBefore = await btcbUser.balanceOf(user17Addr); + await expect(vBTC.connect(user17).repayBorrow(repayAmount)).to.emit(vBTC, "RepayBorrow"); + + expect(await vBTC.borrowBalanceStored(user17Addr)).to.be.closeTo( + borrowBefore.sub(repayAmount), + parseUnits("0.000001", 18), + ); + expect(await btcbUser.balanceOf(user17Addr)).to.equal(uBalBefore.sub(repayAmount)); + }); + + it("borrow succeeds — capacity restored to spot levels", async () => { + // No protection → bounded = spot. Plenty of headroom ($5000+) + const borrowAmt = parseUnits("0.01", 18); + const btcb17 = BEP20__factory.connect(BTCB_ADDR, user17); + const uBalBefore = await btcb17.balanceOf(user17Addr); + const borrowBefore = await vBTC.borrowBalanceStored(user17Addr); + await expect(vBTC.connect(user17).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + + expect(await btcb17.balanceOf(user17Addr)).to.equal(uBalBefore.add(borrowAmt)); + expect(await vBTC.borrowBalanceStored(user17Addr)).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + + it("redeem succeeds — collateral valued at spot", async () => { + // Small redeem — still solvent with plenty of headroom + const redeemAmount = parseUnits("500", 18); + const usdtUser17 = BEP20__factory.connect(USDT_ADDR, user17); + const uBalBefore = await usdtUser17.balanceOf(user17Addr); + await expect(vUSDT.connect(user17).redeemUnderlying(redeemAmount)).to.emit(vUSDT, "Redeem"); + + expect(await usdtUser17.balanceOf(user17Addr)).to.equal(uBalBefore.add(redeemAmount)); + }); + + it("exitMarket succeeds for market with no borrows", async () => { + // User hasn't borrowed from vUSDT, only from vBTC + // Can't exit vUSDT because it's collateral for the BTC borrow + // Test with a fresh user that has no borrows + const exitUser = ethers.Wallet.createRandom().connect(ethers.provider); + const exitAddr = await exitUser.getAddress(); + await setBalance(exitAddr, parseUnits("10", 18)); + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(exitAddr, parseUnits("100", 18)); + const usdtExit = BEP20__factory.connect(USDT_ADDR, exitUser); + await usdtExit.approve(vUSDT_ADDRESS, parseUnits("100", 18)); + await vUSDT.connect(exitUser).mint(parseUnits("100", 18)); + await comptroller.connect(exitUser).enterMarkets([vUSDT_ADDRESS]); + + const errCode = await comptroller.connect(exitUser).callStatic.exitMarket(vUSDT_ADDRESS); + expect(errCode).to.equal(0); + }); + + it("liquidateBorrow returns INSUFFICIENT_SHORTFALL — solvent at spot", async () => { + const liquidator = ethers.Wallet.createRandom().connect(ethers.provider); + await setBalance(await liquidator.getAddress(), parseUnits("10", 18)); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.1", 18)); + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.1", 18)); + + await expect( + vBTC.connect(liquidator).liquidateBorrow(user17Addr, parseUnits("0.02", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); + }); + + it("getBorrowingPower and getAccountLiquidity both show solvency", async () => { + const [cfErr, cfLiquidity, cfShortfall] = await comptroller.getBorrowingPower(user17Addr); + const [ltErr, ltLiquidity, ltShortfall] = await comptroller.getAccountLiquidity(user17Addr); + expect(cfErr).to.equal(0); + expect(ltErr).to.equal(0); + expect(cfLiquidity).to.be.gt(0); + expect(ltLiquidity).to.be.gt(0); + expect(cfShortfall).to.equal(0); + expect(ltShortfall).to.equal(0); + }); + + it("claimVenus succeeds normally", async () => { + await expect(comptroller.connect(user17)["claimVenus(address,address[])"](user17Addr, [vUSDT_ADDRESS])).to.not + .be.reverted; + }); + }); + + // ===================================================================== + // Part 18: Oracle vs DBO Price Divergence Cycle + // ===================================================================== + describe("18. Oracle vs DBO price divergence through protection lifecycle", () => { + let user19: Signer; + let user19Addr: string; + + before(async () => { + user19 = ethers.Wallet.createRandom().connect(ethers.provider); + user19Addr = await user19.getAddress(); + await setBalance(user19Addr, parseUnits("10", 18)); + + await neutralizeDBO(); + + // Supply USDT + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user19Addr, parseUnits("10000", 18)); + const usdtUser = BEP20__factory.connect(USDT_ADDR, user19); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(user19).mint(parseUnits("10000", 18)); + await comptroller.connect(user19).enterMarkets([vUSDT_ADDRESS]); + }); + + it("Phase 1: no protection — DBO prices equal spot", async () => { + const spot = await fakeOracle.getUnderlyingPrice(vUSDT_ADDRESS); + const [collPrice, debtPrice] = await dbo.getBoundedPricesView(vUSDT_ADDRESS); + expect(collPrice).to.equal(spot); + expect(debtPrice).to.equal(spot); + }); + + it("Phase 2: pump triggers protection — DBO collateral < spot", async () => { + pumpUSDTPrice(); // $1 → $1.50 + await dbo.updateProtectionState(vUSDT_ADDRESS); + + const spot = await fakeOracle.getUnderlyingPrice(vUSDT_ADDRESS); + expect(spot).to.equal(USDT_PUMPED); + + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + + const [collPrice, debtPrice] = await dbo.getBoundedPricesView(vUSDT_ADDRESS); + // After neutralizeDBO, windowMin=$0.99. Collateral = min($1.50, $0.99) = $0.99 + const NEUTRALIZED_MIN = USDT_PRICE.mul(99).div(100); + expect(collPrice).to.equal(NEUTRALIZED_MIN); + // Debt bounded at window max ($1.50) = spot (max expanded) + expect(debtPrice).to.equal(USDT_PUMPED); + }); + + it("Phase 3: spot normalizes, protection still active — debt > spot", async () => { + resetPrices(); // back to $1 + + const spot = await fakeOracle.getUnderlyingPrice(vUSDT_ADDRESS); + expect(spot).to.equal(USDT_PRICE); + + // Protection still active (cooldown not elapsed) + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + + const [collPrice, debtPrice] = await dbo.getBoundedPricesView(vUSDT_ADDRESS); + // Collateral = min(spot=$1, windowMin=$0.99) = $0.99 + const NEUTRALIZED_MIN = USDT_PRICE.mul(99).div(100); + expect(collPrice).to.equal(NEUTRALIZED_MIN); + // Debt = max(spot=$1, windowMax=$1.50) = $1.50 > spot + expect(debtPrice).to.equal(USDT_PUMPED); + }); + + it("Phase 4: protection disabled — DBO prices equal spot again", async () => { + await time.increase(COOLDOWN_PERIOD + 1); + + // Narrow window to allow disable + await dbo.connect(timelock).updateMaxPrice(USDT_ADDR, USDT_PRICE.mul(101).div(100)); + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, USDT_PRICE.mul(99).div(100)); + await dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR); + + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.false; + + const spot = await fakeOracle.getUnderlyingPrice(vUSDT_ADDRESS); + const [collPrice, debtPrice] = await dbo.getBoundedPricesView(vUSDT_ADDRESS); + expect(collPrice).to.equal(spot); + expect(debtPrice).to.equal(spot); + }); + }); + + // ===================================================================== + // Part 19: Full Protection Lifecycle + // ===================================================================== + describe("19. Full lifecycle: configure → pump → block → disable → allow", () => { + let user20: Signer; + let user20Addr: string; + + before(async () => { + user20 = ethers.Wallet.createRandom().connect(ethers.provider); + user20Addr = await user20.getAddress(); + await setBalance(user20Addr, parseUnits("10", 18)); + + await neutralizeDBO(); + }); + + it("Step 1: asset configured — bounded pricing enabled, protection inactive", async () => { + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.isBoundedPricingEnabled).to.be.true; + expect(config.currentlyUsingProtectedPrice).to.be.false; + }); + + it("Step 2: set up position — supply USDT, borrow BTC", async () => { + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user20Addr, parseUnits("10000", 18)); + const usdtUser = BEP20__factory.connect(USDT_ADDR, user20); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await expect(vUSDT.connect(user20).mint(parseUnits("10000", 18))).to.emit(vUSDT, "Mint"); + await comptroller.connect(user20).enterMarkets([vUSDT_ADDRESS]); + + // Borrow 95% capacity + const [, capacity] = await comptroller.getBorrowingPower(user20Addr); + const borrowBtc = capacity.mul(95).div(100).mul(parseUnits("1", 18)).div(BTCB_PRICE); + const btcb20 = BEP20__factory.connect(BTCB_ADDR, user20); + const uBalBefore = await btcb20.balanceOf(user20Addr); + const borrowBefore = await vBTC.borrowBalanceStored(user20Addr); + await expect(vBTC.connect(user20).borrow(borrowBtc)).to.emit(vBTC, "Borrow"); + expect(await btcb20.balanceOf(user20Addr)).to.equal(uBalBefore.add(borrowBtc)); + expect(await vBTC.borrowBalanceStored(user20Addr)).to.be.closeTo( + borrowBefore.add(borrowBtc), + parseUnits("0.000001", 18), + ); + }); + + it("Step 3: pump triggers protection — actions blocked", async () => { + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + + // Borrow reverts + await expect(vBTC.connect(user20).borrow(parseUnits("0.01", 18))).to.be.revertedWith("math error"); + // Redeem reverts + await expect(vUSDT.connect(user20).redeemUnderlying(parseUnits("1000", 18))).to.be.revertedWith("math error"); + // Transfer emits Failure + const dst = ethers.Wallet.createRandom().connect(ethers.provider); + await expect(vUSDT.connect(user20).transfer(await dst.getAddress(), parseUnits("1000", 18))).to.emit( + vUSDT, + "Failure", + ); + }); + + it("Step 4: advance cooldown, keeper disables protection", async () => { + await time.increase(COOLDOWN_PERIOD + 1); + resetPrices(); + + await dbo.connect(timelock).updateMaxPrice(USDT_ADDR, USDT_PRICE.mul(101).div(100)); + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, USDT_PRICE.mul(99).div(100)); + await dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR); + + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.false; + }); + + it("Step 5: actions allowed again — borrow succeeds with balance check", async () => { + // Repay some debt first to create headroom + const repayAmt = parseUnits("0.05", 18); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(user20Addr, repayAmt); + const btcb20 = BEP20__factory.connect(BTCB_ADDR, user20); + await btcb20.approve(vBTC_ADDRESS, repayAmt); + const borrowBeforeRepay = await vBTC.borrowBalanceStored(user20Addr); + await expect(vBTC.connect(user20).repayBorrow(repayAmt)).to.emit(vBTC, "RepayBorrow"); + expect(await vBTC.borrowBalanceStored(user20Addr)).to.be.closeTo( + borrowBeforeRepay.sub(repayAmt), + parseUnits("0.000001", 18), + ); + + // Small borrow succeeds + const smallBorrow = parseUnits("0.001", 18); + const uBalBefore = await btcb20.balanceOf(user20Addr); + const borrowBefore = await vBTC.borrowBalanceStored(user20Addr); + await expect(vBTC.connect(user20).borrow(smallBorrow)).to.emit(vBTC, "Borrow"); + expect(await btcb20.balanceOf(user20Addr)).to.equal(uBalBefore.add(smallBorrow)); + expect(await vBTC.borrowBalanceStored(user20Addr)).to.be.closeTo( + borrowBefore.add(smallBorrow), + parseUnits("0.000001", 18), + ); + }); + }); + + // ===================================================================== + // Part 20: Multi-Asset Protection Independence + // ===================================================================== + describe("20. Multi-asset protection independence", () => { + it("protection on USDT does not block user with only BTC collateral", async () => { + await neutralizeDBO(); + + // Pump USDT to trigger protection + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + const config = await dbo.assetProtectionConfig(USDT_ADDR); + expect(config.currentlyUsingProtectedPrice).to.be.true; + + // BTC should NOT be protected + const btcConfig = await dbo.assetProtectionConfig(BTCB_ADDR); + expect(btcConfig.currentlyUsingProtectedPrice).to.be.false; + + // Fresh user with BTC collateral can still borrow + const freshUser = ethers.Wallet.createRandom().connect(ethers.provider); + const freshAddr = await freshUser.getAddress(); + await setBalance(freshAddr, parseUnits("10", 18)); + + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(freshAddr, parseUnits("0.1", 18)); + + const btcbFresh = BEP20__factory.connect(BTCB_ADDR, freshUser); + await btcbFresh.approve(vBTC_ADDRESS, parseUnits("0.1", 18)); + await vBTC.connect(freshUser).mint(parseUnits("0.1", 18)); + await comptroller.connect(freshUser).enterMarkets([vBTC_ADDRESS]); + + // Borrow small USDT against BTC collateral + const borrowAmt = parseUnits("100", 18); + const usdtFresh = BEP20__factory.connect(USDT_ADDR, freshUser); + const uBalBefore = await usdtFresh.balanceOf(freshAddr); + const borrowBefore = await vUSDT.borrowBalanceStored(freshAddr); + await expect(vUSDT.connect(freshUser).borrow(borrowAmt)).to.emit(vUSDT, "Borrow"); + expect(await usdtFresh.balanceOf(freshAddr)).to.equal(uBalBefore.add(borrowAmt)); + expect(await vUSDT.borrowBalanceStored(freshAddr)).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + }); + + // ===================================================================== + // Part 21: Re-enable Protection After Disable + // ===================================================================== + describe("21. Re-enable protection after disable", () => { + it("trigger → disable → re-pump → re-trigger — borrow blocked, allowed, blocked again", async () => { + await neutralizeDBO(); + + // Set up a user with USDT collateral, borrow near max + const user21 = ethers.Wallet.createRandom().connect(ethers.provider); + const user21Addr = await user21.getAddress(); + await setBalance(user21Addr, parseUnits("10", 18)); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user21Addr, parseUnits("10000", 18)); + const usdtUser = BEP20__factory.connect(USDT_ADDR, user21); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(user21).mint(parseUnits("10000", 18)); + await comptroller.connect(user21).enterMarkets([vUSDT_ADDRESS]); + + // Borrow 95% of capacity to make position tight + const [, capacity] = await comptroller.getBorrowingPower(user21Addr); + const borrowBtc = capacity.mul(95).div(100).mul(parseUnits("1", 18)).div(BTCB_PRICE); + await vBTC.connect(user21).borrow(borrowBtc); + + // First trigger — pump activates protection + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + expect((await dbo.assetProtectionConfig(USDT_ADDR)).currentlyUsingProtectedPrice).to.be.true; + + // Borrow blocked — bounded prices restrict capacity + await expect(vBTC.connect(user21).borrow(parseUnits("0.01", 18))).to.be.revertedWith("math error"); + + // Disable protection + await time.increase(COOLDOWN_PERIOD + 1); + resetPrices(); + await dbo.connect(timelock).updateMaxPrice(USDT_ADDR, USDT_PRICE.mul(101).div(100)); + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, USDT_PRICE.mul(99).div(100)); + await dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR); + expect((await dbo.assetProtectionConfig(USDT_ADDR)).currentlyUsingProtectedPrice).to.be.false; + + // Borrow now allowed — protection disabled, spot prices used + await expect(vBTC.connect(user21).borrow(parseUnits("0.001", 18))).to.not.be.reverted; + + // Re-pump triggers protection again + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + expect((await dbo.assetProtectionConfig(USDT_ADDR)).currentlyUsingProtectedPrice).to.be.true; + + // Borrow blocked again — bounded prices re-applied + await expect(vBTC.connect(user21).borrow(parseUnits("0.01", 18))).to.be.revertedWith("math error"); + }); + }); + + // ===================================================================== + // Part 22: Liquidation During Protection on Collateral Only + // ===================================================================== + describe("22. Liquidation during protection on collateral asset only", () => { + it("USDT protected, BTCB not — LT uses spot, protection irrelevant", async () => { + await neutralizeDBO(); + + // Set up user with USDT collateral, BTC borrow + const user25 = ethers.Wallet.createRandom().connect(ethers.provider); + const addr25 = await user25.getAddress(); + await setBalance(addr25, parseUnits("10", 18)); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(addr25, parseUnits("10000", 18)); + const usdtU = BEP20__factory.connect(USDT_ADDR, user25); + await usdtU.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(user25).mint(parseUnits("10000", 18)); + await comptroller.connect(user25).enterMarkets([vUSDT_ADDRESS]); + await vBTC.connect(user25).borrow(parseUnits("0.01", 18)); + + // Trigger protection on USDT only + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + expect((await dbo.assetProtectionConfig(USDT_ADDR)).currentlyUsingProtectedPrice).to.be.true; + expect((await dbo.assetProtectionConfig(BTCB_ADDR)).currentlyUsingProtectedPrice).to.be.false; + + // Liquidation uses LT spot — borrower solvent at pumped $1.50 + // LT: 10000 * $1.50 * 0.9 = $13500 >> 0.01 * $60k = $600 + const liq25 = ethers.Wallet.createRandom().connect(ethers.provider); + await setBalance(await liq25.getAddress(), parseUnits("10", 18)); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liq25.getAddress(), parseUnits("0.01", 18)); + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liq25); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.01", 18)); + + await expect(vBTC.connect(liq25).liquidateBorrow(addr25, parseUnits("0.005", 18), vUSDT.address)).to.emit( + vBTC, + "Failure", + ); // INSUFFICIENT_SHORTFALL — protection doesn't affect LT + }); + }); + + // ===================================================================== + // Part 23: getBorrowingPower vs getAccountLiquidity Divergence + // ===================================================================== + describe("23. getBorrowingPower vs getAccountLiquidity divergence through cycle", () => { + let user26: Signer; + let user26Addr: string; + + before(async () => { + user26 = ethers.Wallet.createRandom().connect(ethers.provider); + user26Addr = await user26.getAddress(); + await setBalance(user26Addr, parseUnits("10", 18)); + + await neutralizeDBO(); + + // Set CF=0.7, LT=0.9 on vUSDT for deterministic divergence (mainnet has CF==LT==0.8) + await comptroller["setCollateralFactor(address,uint256,uint256)"]( + vUSDT_ADDRESS, + parseUnits("0.7", 18), + parseUnits("0.9", 18), + ); + + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user26Addr, parseUnits("10000", 18)); + const usdtU = BEP20__factory.connect(USDT_ADDR, user26); + await usdtU.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(user26).mint(parseUnits("10000", 18)); + await comptroller.connect(user26).enterMarkets([vUSDT_ADDRESS]); + + // Borrow 50% of capacity + const [, capacity] = await comptroller.getBorrowingPower(user26Addr); + const borrowBtc = capacity.mul(50).div(100).mul(parseUnits("1", 18)).div(BTCB_PRICE); + await vBTC.connect(user26).borrow(borrowBtc); + }); + + it("normal prices: both show solvency, LT (0.9) > CF (0.7)", async () => { + const [cfErr, cfLiquidity, cfShortfall] = await comptroller.getBorrowingPower(user26Addr); + const [ltErr, ltLiquidity, ltShortfall] = await comptroller.getAccountLiquidity(user26Addr); + expect(cfErr).to.equal(0); + expect(ltErr).to.equal(0); + expect(cfLiquidity).to.be.gt(0); + expect(ltLiquidity).to.be.gt(0); + expect(cfShortfall).to.equal(0); + expect(ltShortfall).to.equal(0); + // LT=0.9 > CF=0.7 → ltLiquidity > cfLiquidity + expect(ltLiquidity).to.be.gt(cfLiquidity); + }); + + it("pump: CF may show reduced capacity, LT sees pumped spot — max divergence", async () => { + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + + const [, cfLiquidity, cfShortfall] = await comptroller.getBorrowingPower(user26Addr); + const [, ltLiquidity] = await comptroller.getAccountLiquidity(user26Addr); + + // CF uses bounded $1 → capacity capped + // LT uses pumped $1.50 → capacity increased + expect(ltLiquidity).to.be.gt(cfLiquidity.add(cfShortfall)); + }); + + it("after disable: both converge back", async () => { + await time.increase(COOLDOWN_PERIOD + 1); + resetPrices(); + await dbo.connect(timelock).updateMaxPrice(USDT_ADDR, USDT_PRICE.mul(101).div(100)); + await dbo.connect(timelock).updateMinPrice(USDT_ADDR, USDT_PRICE.mul(99).div(100)); + await dbo.connect(timelock).disableActiveProtectedPrice(USDT_ADDR); + + const [, cfLiquidity] = await comptroller.getBorrowingPower(user26Addr); + const [, ltLiquidity] = await comptroller.getAccountLiquidity(user26Addr); + + // Both show solvency, LT still > CF due to weighting + expect(cfLiquidity).to.be.gt(0); + expect(ltLiquidity).to.be.gt(0); + expect(ltLiquidity).to.be.gt(cfLiquidity); + }); + }); + + // ===================================================================== + // Part 24: Borrow Token Crash (Debt Deflation) + // ===================================================================== + describe("24. Borrow token crash — DBO bounds debt at window max", () => { + let borrower26: Signer; + let borrower26Addr: string; + + before(async () => { + borrower26 = ethers.Wallet.createRandom().connect(ethers.provider); + borrower26Addr = await borrower26.getAddress(); + await setBalance(borrower26Addr, parseUnits("10", 18)); + + await neutralizeDBO(); + + // Supply 50000 USDT + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(borrower26Addr, parseUnits("50000", 18)); + const usdtUser = BEP20__factory.connect(USDT_ADDR, borrower26); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("50000", 18)); + await vUSDT.connect(borrower26).mint(parseUnits("50000", 18)); + await comptroller.connect(borrower26).enterMarkets([vUSDT_ADDRESS]); + + // Borrow 0.5 BTC at normal $60k = $30000 (within $40000 capacity) + await vBTC.connect(borrower26).borrow(parseUnits("0.5", 18)); + + // Crash BTC from $60k to $42k + crashBTCBPrice(); + }); + + it("borrow reverts — bounded debt at $60k blocks over-borrowing cheap BTC", async () => { + // DBO bounds BTC debt at window max ($60k), not spot $42k + // Existing debt: 0.5 BTC * $60k (bounded) = $30000 + // Capacity: 50000 * $1 * 0.8 = $40000. Remaining: $10000 + // Try 0.2 BTC: at bounded $60k = $12000 > $10000 remaining → blocked + await expect(vBTC.connect(borrower26).borrow(parseUnits("0.2", 18))).to.be.revertedWith("math error"); + }); + + it("borrow succeeds within bounded capacity", async () => { + // 0.05 BTC at bounded $60k = $3000 < ~$10000 remaining → OK + const borrowAmt = parseUnits("0.05", 18); + const btcb26 = BEP20__factory.connect(BTCB_ADDR, borrower26); + const uBalBefore = await btcb26.balanceOf(borrower26Addr); + const borrowBefore = await vBTC.borrowBalanceStored(borrower26Addr); + + await expect(vBTC.connect(borrower26).borrow(borrowAmt)).to.emit(vBTC, "Borrow"); + + expect(await btcb26.balanceOf(borrower26Addr)).to.equal(uBalBefore.add(borrowAmt)); + expect(await vBTC.borrowBalanceStored(borrower26Addr)).to.be.closeTo( + borrowBefore.add(borrowAmt), + parseUnits("0.000001", 18), + ); + }); + + it("liquidation uses spot $42k for BTC debt — borrower very solvent", async () => { + // LT: 50000 * $1 * 0.8 = $40000. Debt at spot $42k: ~0.6 BTC * $42k = $25200 → solvent + const liquidator = ethers.Wallet.createRandom().connect(ethers.provider); + await setBalance(await liquidator.getAddress(), parseUnits("10", 18)); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.1", 18)); + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.1", 18)); + + await expect( + vBTC.connect(liquidator).liquidateBorrow(borrower26Addr, parseUnits("0.05", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); // INSUFFICIENT_SHORTFALL + }); + + it("getBorrowingPower uses bounded $60k debt — capacity reduced vs spot", async () => { + // At bounded $60k: debt is valued higher than spot $42k → less remaining capacity + const [, cfLiquidity] = await comptroller.getBorrowingPower(borrower26Addr); + const [, ltLiquidity] = await comptroller.getAccountLiquidity(borrower26Addr); + + // CF uses bounded → debt valued at $60k → tighter capacity + // LT uses spot $42k → debt valued lower → more headroom + expect(ltLiquidity).to.be.gt(cfLiquidity); + }); + }); + + // ===================================================================== + // Part 25: Extreme Volatility — Price Swings Past Max AND Below Min + // ===================================================================== + describe("25. Extreme volatility — price swings past max and below min", () => { + let user27: Signer; + let user27Addr: string; + + before(async () => { + user27 = ethers.Wallet.createRandom().connect(ethers.provider); + user27Addr = await user27.getAddress(); + await setBalance(user27Addr, parseUnits("10", 18)); + + await neutralizeDBO(); + + // Supply 10000 USDT + const whale = await initMainnetUser(USDT_WHALE, parseUnits("1")); + const usdt = BEP20__factory.connect(USDT_ADDR, whale); + await usdt.transfer(user27Addr, parseUnits("10000", 18)); + const usdtUser = BEP20__factory.connect(USDT_ADDR, user27); + await usdtUser.approve(vUSDT_ADDRESS, parseUnits("10000", 18)); + await vUSDT.connect(user27).mint(parseUnits("10000", 18)); + await comptroller.connect(user27).enterMarkets([vUSDT_ADDRESS]); + + // Borrow small amount at normal prices + await vBTC.connect(user27).borrow(parseUnits("0.01", 18)); + }); + + it("borrowing power collapses through volatility stages", async () => { + // Stage 1 — Normal: record capacity + const [, liqNormal] = await comptroller.getBorrowingPower(user27Addr); + expect(liqNormal).to.be.gt(0); + + // Stage 2 — Pump USDT to $1.50: DBO bounds collateral at $1 + pumpUSDTPrice(); + await dbo.updateProtectionState(vUSDT_ADDRESS); + const [, liqPump] = await comptroller.getBorrowingPower(user27Addr); + // Capacity capped at bounded $1 — should be <= normal + expect(liqPump).to.be.lte(liqNormal); + + // Stage 3 — Crash USDT to $0.30: window expands down + const crashedUsdt = parseUnits("0.3", 18); + fakeOracle.getPrice.whenCalledWith(USDT_ADDR).returns(crashedUsdt); + fakeOracle.getUnderlyingPrice.whenCalledWith(vUSDT_ADDRESS).returns(crashedUsdt); + await dbo.updateProtectionState(vUSDT_ADDRESS); + + const [, liqCrash, shortfallCrash] = await comptroller.getBorrowingPower(user27Addr); + // Capacity collapsed — collateral at $0.30, debt inflated + expect(liqCrash.add(shortfallCrash)).to.be.gt(0); // either liquidity or shortfall exists + // Much worse than normal + expect(liqCrash).to.be.lt(liqNormal); + }); + + it("borrow blocked under extreme volatility", async () => { + // After the pump+crash above, DBO returns extreme bounded prices + // Collateral devalued + debt inflated → borrow blocked + await expect(vBTC.connect(user27).borrow(parseUnits("0.1", 18))).to.be.revertedWith("math error"); + }); + + it("liquidation possible under extreme crash at LT spot", async () => { + // Crash USDT severely — $0.30 spot + // LT: 10000 * $0.30 * 0.8 = $2400 vs debt = 0.01 BTC * $60k = $600 → still solvent for small borrow + // Need larger borrow to be underwater. Let's check current state. + const [, , ltShortfall] = await comptroller.getAccountLiquidity(user27Addr); + + if (ltShortfall.gt(0)) { + // User is underwater at LT — liquidation should succeed + const liquidator = ethers.Wallet.createRandom().connect(ethers.provider); + await setBalance(await liquidator.getAddress(), parseUnits("10", 18)); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.01", 18)); + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.01", 18)); + + const debtBefore = await vBTC.borrowBalanceStored(user27Addr); + await vBTC.connect(liquidator).liquidateBorrow(user27Addr, parseUnits("0.005", 18), vUSDT.address); + expect(await vBTC.borrowBalanceStored(user27Addr)).to.be.closeTo( + debtBefore.sub(parseUnits("0.005", 18)), + parseUnits("0.000001", 18), + ); + } else { + // User solvent at LT — liquidation should fail + const liquidator = ethers.Wallet.createRandom().connect(ethers.provider); + await setBalance(await liquidator.getAddress(), parseUnits("10", 18)); + const btcbWhale = await initMainnetUser(BTCB_WHALE, parseUnits("1")); + const btcb = BEP20__factory.connect(BTCB_ADDR, btcbWhale); + await btcb.transfer(await liquidator.getAddress(), parseUnits("0.01", 18)); + const btcbLiq = BEP20__factory.connect(BTCB_ADDR, liquidator); + await btcbLiq.approve(vBTC_ADDRESS, parseUnits("0.01", 18)); + + await expect( + vBTC.connect(liquidator).liquidateBorrow(user27Addr, parseUnits("0.005", 18), vUSDT.address), + ).to.emit(vBTC, "Failure"); // INSUFFICIENT_SHORTFALL + } + }); + }); + }); + }); +} diff --git a/tests/hardhat/Prime/Prime.ts b/tests/hardhat/Prime/Prime.ts index e53bac6a4..eccb6810e 100644 --- a/tests/hardhat/Prime/Prime.ts +++ b/tests/hardhat/Prime/Prime.ts @@ -13,6 +13,7 @@ import { ComptrollerMock, ComptrollerMock__factory, IAccessControlManager, + IDeviationBoundedOracle, InterestRateModelHarness, PrimeLiquidityProvider, PrimeScenario, @@ -51,6 +52,8 @@ async function deployProtocol(): Promise { const [wallet, user1, user2, user3] = await ethers.getSigners(); const oracle = await smock.fake("ResilientOracleInterface"); + const deviationBoundedOracle = await smock.fake("IDeviationBoundedOracle"); + deviationBoundedOracle.getBoundedPricesView.returns([convertToUnit(1, 18), convertToUnit(1, 18)]); const accessControl = await smock.fake("AccessControlManager"); accessControl.isAllowedToCall.returns(true); const ComptrollerLensFactory = await smock.mock("ComptrollerLens"); @@ -60,6 +63,7 @@ async function deployProtocol(): Promise { await comptroller._setAccessControl(accessControl.address); await comptroller._setComptrollerLens(comptrollerLens.address); await comptroller._setPriceOracle(oracle.address); + await comptroller.setDeviationBoundedOracle(deviationBoundedOracle.address); const tokenFactory = await ethers.getContractFactory("BEP20Harness"); const usdt = (await tokenFactory.deploy( diff --git a/tests/hardhat/VAI/VAIController.ts b/tests/hardhat/VAI/VAIController.ts index 9aecd51f9..47ead5ca3 100644 --- a/tests/hardhat/VAI/VAIController.ts +++ b/tests/hardhat/VAI/VAIController.ts @@ -1,26 +1,32 @@ import { FakeContract, MockContract, smock } from "@defi-wonderland/smock"; import { loadFixture, mineUpTo } from "@nomicfoundation/hardhat-network-helpers"; -import { expect } from "chai"; +import chai from "chai"; import { BigNumber, Wallet, constants } from "ethers"; import { parseUnits } from "ethers/lib/utils"; -import { ethers } from "hardhat"; +import { ethers, upgrades } from "hardhat"; import { + BEP20Harness, ComptrollerLens__factory, ComptrollerMock, ComptrollerMock__factory, IAccessControlManagerV8, + IDeviationBoundedOracle, + IDeviationBoundedOracle__factory, IProtocolShareReserve, + InterestRateModelHarness, PrimeScenario__factory, + SimplePriceOracle, + VAIControllerHarness, VAIControllerHarness__factory, + VAIScenario, + VBep20Harness, + XVS, } from "../../../typechain"; -import { SimplePriceOracle } from "../../../typechain"; -import { XVS } from "../../../typechain"; -import { VAIScenario } from "../../../typechain"; -import { VAIControllerHarness } from "../../../typechain"; -import { BEP20Harness } from "../../../typechain"; -import { VBep20Harness } from "../../../typechain"; -import { InterestRateModelHarness } from "../../../typechain"; + +chai.use(smock.matchers); + +const { expect } = chai; export const bigNumber18 = BigNumber.from("1000000000000000000"); // 1e18 export const bigNumber17 = BigNumber.from("100000000000000000"); //1e17 @@ -39,6 +45,8 @@ interface ComptrollerFixture { vai: VAIScenario; vaiController: MockContract; vusdt: VBep20Harness; + /** Same address as `comptroller.deviationBoundedOracle()` — what `getMintableVAI` uses on-chain. */ + deviationBoundedOracle: IDeviationBoundedOracle; } describe("VAIController", async () => { @@ -54,13 +62,14 @@ describe("VAIController", async () => { let vaiController: MockContract; let usdt: BEP20Harness; let vusdt: VBep20Harness; + let deviationBoundedOracle: IDeviationBoundedOracle; let protocolShareReserve: FakeContract; before("get signers", async () => { [wallet, user1, user2, treasuryGuardian, treasuryAddress] = await (ethers as any).getSigners(); }); - async function comptrollerFixture(): Promise { + async function deployComptrollerFixture(): Promise { const testTokenFactory = await ethers.getContractFactory("BEP20Harness"); const usdt = (await testTokenFactory.deploy( bigNumber18.mul(100000000), @@ -113,6 +122,16 @@ describe("VAIController", async () => { ); await comptroller._setVAIMintRate(BigNumber.from(10000)); await vaiController.setReceiver(treasuryAddress.address); + + const DBOFactory = await ethers.getContractFactory("DeviationBoundedOracle"); + const dbo = await upgrades.deployProxy(DBOFactory, [accessControl.address], { + constructorArgs: [priceOracle.address, user2.address, vai.address], + initializer: "initialize", + unsafeAllow: ["state-variable-immutable"], + }); + await comptroller.setDeviationBoundedOracle(dbo.address); + const deviationBoundedOracle = IDeviationBoundedOracle__factory.connect(dbo.address, ethers.provider); + await vaiController.initialize(); const interestRateModelHarnessFactory = await ethers.getContractFactory("InterestRateModelHarness"); @@ -142,12 +161,17 @@ describe("VAIController", async () => { ); await vusdt.setProtocolShareReserve(protocolShareReserve.address); await comptroller["setLiquidationIncentive(address,uint256)"](vusdt.address, liquidationIncentive); - return { usdt, accessControl, comptroller, priceOracle, vai, vaiController, vusdt }; + return { usdt, accessControl, comptroller, priceOracle, vai, vaiController, vusdt, deviationBoundedOracle }; + } + + async function comptrollerFixture(): Promise { + return deployComptrollerFixture(); } beforeEach("deploy Comptroller", async () => { - ({ usdt, accessControl, comptroller, priceOracle, vai, vaiController, vusdt } = + ({ usdt, accessControl, comptroller, priceOracle, vai, vaiController, vusdt, deviationBoundedOracle } = await loadFixture(comptrollerFixture)); + expect(deviationBoundedOracle.address).to.eq(await comptroller.deviationBoundedOracle()); accessControl.isAllowedToCall.reset(); accessControl.isAllowedToCall.returns(true); await vusdt.setAccessControlManager(accessControl.address); @@ -192,6 +216,117 @@ describe("VAIController", async () => { const res = await vaiController.getMintableVAI(user1.address); expect(res[1]).to.eq(bigNumber18.mul(100)); }); + + describe("getMintableVAI vs DeviationBoundedOracle", () => { + // --- Shared fixture numbers (must match comptrollerFixture / beforeEach) --- + /** Spot price of vUSDT underlying from `SimplePriceOracle` (USD per 1 underlying, 1e18 scale). */ + const SPOT_UNDERLYING_PRICE = bigNumber18; + /** vUSDT balance for user1 after `harnessSetBalance`. */ + const USER_VTOKEN_BALANCE = bigNumber18.mul(200); + /** Stored exchange rate mantissa (1 vToken : underlying). */ + const EXCHANGE_RATE_MANTISSA = bigNumber18; + /** Collateral factor mantissa (50%). */ + const COLLATERAL_FACTOR_MANTISSA = bigNumber17.mul(5); + /** `vaiMintRate` on comptroller in basis points;10000 => 100% of supply liquidity counts toward mint cap. */ + const VAI_MINT_RATE_BPS = 10000; + + it("real DBO + SimplePriceOracle: bounded view tracks spot when bounded pricing is off; mintable matches closed form", async () => { + /** + * Comptroller uses a real `DeviationBoundedOracle` wired to `SimplePriceOracle` as `RESILIENT_ORACLE`. + * USDT is not configured on the DBO (`isBoundedPricingEnabled` false), so `getBoundedPricesView` returns + * spot from `getPrice(underlying)` — the same mantissa as `getUnderlyingPrice(vUSDT)` on `SimplePriceOracle`. + * + * Expected mintable at $1 (no borrows, no prior VAI debt): + * tokensToDenom = exchangeRate * spotPrice = 1e18 * 1e18 / 1e18 = 1e18 + * supplyValue = tokensToDenom * vTokenBalance / 1e18 = 1e18 * 200e18 / 1e18 = 200e18 + * after CF = supplyValue * CF / 1e18 = 200e18 * 0.5e18 / 1e18 = 100e18 + * mintable = sumSupply * vaiMintRate / 10000 - borrowEffects = 100e18 * 10000/10000 - 0 = 100e18 + */ + const spotPx = await priceOracle.getUnderlyingPrice(vusdt.address); + expect(spotPx).to.eq(SPOT_UNDERLYING_PRICE); + expect(await priceOracle.getPrice(usdt.address)).to.eq(SPOT_UNDERLYING_PRICE); + + const [boundedCollateral, boundedDebt] = await deviationBoundedOracle.getBoundedPricesView(vusdt.address); + expect(boundedCollateral).to.eq(SPOT_UNDERLYING_PRICE); + expect(boundedDebt).to.eq(SPOT_UNDERLYING_PRICE); + + const snapshot = await vusdt.getAccountSnapshot(user1.address); + expect(snapshot[1]).to.eq(USER_VTOKEN_BALANCE); + expect(snapshot[3]).to.eq(EXCHANGE_RATE_MANTISSA); + + const cfData = await comptroller.markets(vusdt.address); + expect(cfData.collateralFactorMantissa).to.eq(COLLATERAL_FACTOR_MANTISSA); + expect(await comptroller.vaiMintRate()).to.eq(VAI_MINT_RATE_BPS); + + const expectedMintable = bigNumber18.mul(100); + const [, mintable] = await vaiController.getMintableVAI(user1.address); + expect(mintable).to.eq(expectedMintable); + + const spot10 = parseUnits("10", 18); + await priceOracle.setUnderlyingPrice(vusdt.address, spot10); + expect(await priceOracle.getUnderlyingPrice(vusdt.address)).to.eq(spot10); + expect(await priceOracle.getPrice(usdt.address)).to.eq(spot10); + const [c10, d10] = await deviationBoundedOracle.getBoundedPricesView(vusdt.address); + expect(c10).to.eq(spot10); + expect(d10).to.eq(spot10); + const [, mintable10] = await vaiController.getMintableVAI(user1.address); + expect(mintable10).to.eq(parseUnits("1000", 18)); + }); + + it("real DBO: keeper pulls window min below spot → deviation → conservative collateral and lower mintable", async () => { + /** + * `setTokenConfig` seeds the window at spot ($1–$1); views still return spot until the window disagrees with spot. + * `updateMinPrice` to $0.8 while spot stays $1 makes spot exceed `min * (1 + triggerThreshold)` (10%), + * so bounded collateral becomes min(spot, windowMin) and mintable drops (no borrows → debt leg unused). + */ + const dbo = deviationBoundedOracle.connect(wallet); + + const WINDOW_MIN = parseUnits("0.8", 18); + const TRIGGER_THRESHOLD = parseUnits("0.1", 18); + const RESET_THRESHOLD = parseUnits("0.05", 18); + + const spotPxBefore = await priceOracle.getUnderlyingPrice(vusdt.address); + expect(spotPxBefore).to.eq(SPOT_UNDERLYING_PRICE); + + await dbo.setTokenConfig({ + asset: usdt.address, + cooldownPeriod: 3600, + triggerThreshold: TRIGGER_THRESHOLD, + resetThreshold: RESET_THRESHOLD, + enableBoundedPricing: true, + enableCaching: true, + }); + + const [, mintableAtSpotBounded] = await vaiController.getMintableVAI(user1.address); + expect(mintableAtSpotBounded).to.eq(bigNumber18.mul(100)); + + await dbo.updateMinPrice(usdt.address, WINDOW_MIN); + // State-changing path sets `currentlyUsingProtectedPrice` when deviation is detected; views alone do not. + await dbo.updateProtectionState(vusdt.address); + + const spotPxAfter = await priceOracle.getUnderlyingPrice(vusdt.address); + expect(spotPxAfter).to.eq(SPOT_UNDERLYING_PRICE); + expect(spotPxAfter).to.eq(spotPxBefore); + + const protection = await dbo.assetProtectionConfig(usdt.address); + expect(protection.minPrice).to.eq(WINDOW_MIN); + expect(protection.maxPrice).to.eq(SPOT_UNDERLYING_PRICE); + + const [boundedCol, boundedD] = await dbo.getBoundedPricesView(vusdt.address); + expect(boundedCol).to.eq(WINDOW_MIN); + expect(boundedD).to.eq(SPOT_UNDERLYING_PRICE); + expect(boundedCol).to.not.eq(SPOT_UNDERLYING_PRICE); + expect(await dbo.currentlyUsingProtectedPrice(usdt.address)).to.eq(true); + + /** + * Supply leg scales with bounded collateral price only (still no borrow): + * after CF = 200e18 * 0.8 * 0.5 = 80e18 → mintable 80e18 < 100e18. + */ + const [, mintableUnderProtection] = await vaiController.getMintableVAI(user1.address); + expect(mintableUnderProtection).to.eq(bigNumber18.mul(80)); + expect(mintableUnderProtection.lt(mintableAtSpotBounded)).to.eq(true); + }); + }); }); describe("#mintVAI", async () => { @@ -231,6 +366,73 @@ describe("VAIController", async () => { expect(await comptroller.mintedVAIs(user1.address)).to.eq(parseUnits("32", 18)); expect(await vaiController.pastVAIInterest(user1.address)).to.eq(parseUnits("2", 18)); }); + + describe("L01: persists DBO state for every entered asset", async () => { + let dboFake: FakeContract; + + beforeEach(async () => { + dboFake = await smock.fake("IDeviationBoundedOracle"); + // Stub the view used by getMintableVAI so the mint can compute a non-zero allowance + dboFake.getBoundedPricesView.returns([bigNumber18, bigNumber18]); + await comptroller.setDeviationBoundedOracle(dboFake.address); + }); + + it("calls updateProtectionState for the single entered asset before computing mintable VAI", async () => { + await vaiController.connect(user1).mintVAI(mintAmount); + + expect(dboFake.updateProtectionState).to.have.been.calledOnce; + expect(dboFake.updateProtectionState).to.have.been.calledWith(vusdt.address); + expect(await vai.balanceOf(user1.address)).to.eq(mintAmount); + }); + + it("calls updateProtectionState once per entered asset when the minter is in multiple markets", async () => { + // Spin up a second market and enter it as user1 + const InterestRateModelHarness = await (await ethers.getContractFactory("InterestRateModelHarness")).deploy(0); + const secondVTokenFactory = await ethers.getContractFactory("VBep20Harness"); + const usdc = (await ( + await ethers.getContractFactory("BEP20Harness") + ).deploy(bigNumber18.mul(100000000), "usdc", BigNumber.from(18), "BEP20 usdc")) as BEP20Harness; + const vusdc = (await secondVTokenFactory.deploy( + usdc.address, + comptroller.address, + InterestRateModelHarness.address, + bigNumber18, + "VToken usdc", + "vusdc", + BigNumber.from(18), + wallet.address, + )) as VBep20Harness; + await priceOracle.setUnderlyingPrice(vusdc.address, bigNumber18); + await comptroller._supportMarket(vusdc.address); + await comptroller["setCollateralFactor(address,uint256,uint256)"]( + vusdc.address, + bigNumber17.mul(5), + bigNumber17.mul(5), + ); + await vusdc.setAccessControlManager(accessControl.address); + await vusdc.setProtocolShareReserve(protocolShareReserve.address); + await vusdc.setReduceReservesBlockDelta(10000000000); + await vusdc.harnessSetBalance(user1.address, bigNumber18.mul(200)); + await comptroller.connect(user1).enterMarkets([vusdc.address]); + + // Re-stub on the same instance — beforeEach already set it + dboFake.updateProtectionState.reset(); + + await vaiController.connect(user1).mintVAI(mintAmount); + + const enteredMarkets = await comptroller.getAssetsIn(user1.address); + expect(enteredMarkets.length).to.eq(2); + expect(dboFake.updateProtectionState).to.have.callCount(enteredMarkets.length); + expect(dboFake.updateProtectionState.atCall(0)).to.have.been.calledWith(enteredMarkets[0]); + expect(dboFake.updateProtectionState.atCall(1)).to.have.been.calledWith(enteredMarkets[1]); + }); + + it("propagates revert when DBO.updateProtectionState reverts", async () => { + dboFake.updateProtectionState.reverts("DBO: forced revert"); + + await expect(vaiController.connect(user1).mintVAI(mintAmount)).to.be.reverted; + }); + }); }); describe("#repayVAI", async () => { diff --git a/tests/hardhat/fixtures/ComptrollerWithMarkets.ts b/tests/hardhat/fixtures/ComptrollerWithMarkets.ts index 9dcd7dafb..2921e06b4 100644 --- a/tests/hardhat/fixtures/ComptrollerWithMarkets.ts +++ b/tests/hardhat/fixtures/ComptrollerWithMarkets.ts @@ -11,6 +11,7 @@ import { ComptrollerMock__factory, FaucetToken, IAccessControlManagerV5, + IDeviationBoundedOracle, IERC20, InterestRateModel, InterestRateModelHarness, @@ -28,6 +29,7 @@ type MaybeFake = T | FakeContract; interface ComptrollerFixture { accessControlManager: FakeContract; + deviationBoundedOracle: FakeContract; oracle: FakeContract; vaiController: FakeContract; comptroller: ComptrollerMock; @@ -45,9 +47,10 @@ export const deployComptrollerWithMarkets = async ({ interestRateModel?: InterestRateModel; }): Promise => { const accessControlManager = await deployFakeAccessControlManager(); + const deviationBoundedOracle = await deployFakeDeviationBoundedOracle(); const oracle = await deployFakeOracle(); const comptrollerLens = await deployComptrollerLens(); - const comptroller = await deployComptroller({ accessControlManager, comptrollerLens }); + const comptroller = await deployComptroller({ accessControlManager, comptrollerLens, deviationBoundedOracle }); const protocolShareReserve = await deployProtocolShareReserve(comptroller.address); const vTokens: VBep20[] = []; @@ -68,6 +71,7 @@ export const deployComptrollerWithMarkets = async ({ await comptroller._setVAIController(vaiController.address); return { accessControlManager, + deviationBoundedOracle, oracle, comptroller, comptrollerLens, @@ -131,9 +135,16 @@ export const deployFakeOracle = async (): Promise> => return oracle; }; +export const deployFakeDeviationBoundedOracle = async (): Promise> => { + const deviationBoundedOracle = await smock.fake("IDeviationBoundedOracle"); + deviationBoundedOracle.getBoundedPricesView.returns([parseUnits("1", 18), parseUnits("1", 18)]); + return deviationBoundedOracle; +}; + export const deployComptroller = async ( opts: Partial<{ accessControlManager: MaybeFake; + deviationBoundedOracle: MaybeFake; oracle: MaybeFake; liquidationIncentiveMantissa: BigNumberish; closeFactorMantissa: BigNumberish; @@ -141,6 +152,7 @@ export const deployComptroller = async ( }> = {}, ): Promise => { const acm = opts.accessControlManager ?? (await deployFakeAccessControlManager()); + const deviationBoundedOracle = opts.deviationBoundedOracle ?? (await deployFakeDeviationBoundedOracle()); const oracle = opts.oracle ?? (await deployFakeOracle()); const closeFactorMantissa = opts.closeFactorMantissa ?? parseUnits("0.5", 18); const comptrollerLens = opts.comptrollerLens ?? (await deployComptrollerLens()); @@ -151,6 +163,7 @@ export const deployComptroller = async ( await comptroller._setComptrollerLens(comptrollerLens.address); await comptroller._setAccessControl(acm.address); await comptroller._setPriceOracle(oracle.address); + await comptroller.setDeviationBoundedOracle(deviationBoundedOracle.address); await comptroller._setCloseFactor(closeFactorMantissa); return comptroller; }; diff --git a/tests/hardhat/integration/index.ts b/tests/hardhat/integration/index.ts index 1c0263f6a..ebca8c9ac 100644 --- a/tests/hardhat/integration/index.ts +++ b/tests/hardhat/integration/index.ts @@ -2,6 +2,7 @@ import { FakeContract, MockContract, smock } from "@defi-wonderland/smock"; import { loadFixture, mine } from "@nomicfoundation/hardhat-network-helpers"; import chai from "chai"; import { BigNumber, Signer } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; import { ethers } from "hardhat"; import { convertToUnit } from "../../../helpers/utils"; @@ -12,6 +13,7 @@ import { ComptrollerMock, ComptrollerMock__factory, IAccessControlManager, + IDeviationBoundedOracle, InterestRateModelHarness, Prime, PrimeLiquidityProvider, @@ -32,6 +34,7 @@ export const bigNumber16 = BigNumber.from("10000000000000000"); // 1e16 type SetupProtocolFixture = { oracle: FakeContract; accessControl: FakeContract; + deviationBoundedOracle: FakeContract; comptrollerLens: MockContract; comptroller: MockContract; usdt: BEP20Harness; @@ -45,6 +48,12 @@ type SetupProtocolFixture = { primeLiquidityProvider: PrimeLiquidityProvider; }; +export const deployFakeDeviationBoundedOracle = async (): Promise> => { + const deviationBoundedOracle = await smock.fake("IDeviationBoundedOracle"); + deviationBoundedOracle.getBoundedPricesView.returns([parseUnits("1", 18), parseUnits("1", 18)]); + return deviationBoundedOracle; +}; + async function deployProtocol(): Promise { const [wallet, user1, user2, user3] = await ethers.getSigners(); @@ -55,9 +64,12 @@ async function deployProtocol(): Promise { const ComptrollerFactory = await smock.mock("ComptrollerMock"); const comptroller = await ComptrollerFactory.deploy(); const comptrollerLens = await ComptrollerLensFactory.deploy(); + const deviationBoundedOracle = await deployFakeDeviationBoundedOracle(); + await comptroller._setAccessControl(accessControl.address); await comptroller._setComptrollerLens(comptrollerLens.address); await comptroller._setPriceOracle(oracle.address); + await comptroller.setDeviationBoundedOracle(deviationBoundedOracle.address); const tokenFactory = await ethers.getContractFactory("BEP20Harness"); const usdt = (await tokenFactory.deploy( diff --git a/yarn.lock b/yarn.lock index 740f185b2..0697b4e48 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3175,24 +3175,25 @@ __metadata: languageName: node linkType: hard -"@venusprotocol/oracle@npm:2.10.0": - version: 2.10.0 - resolution: "@venusprotocol/oracle@npm:2.10.0" +"@venusprotocol/oracle@npm:2.15.0": + version: 2.15.0 + resolution: "@venusprotocol/oracle@npm:2.15.0" dependencies: "@chainlink/contracts": ^0.5.1 - "@defi-wonderland/smock": 2.3.5 + "@defi-wonderland/smock": 2.4.0 "@nomicfoundation/hardhat-network-helpers": ^1.0.8 "@openzeppelin/contracts": ^4.6.0 "@openzeppelin/contracts-upgradeable": ^4.7.3 - "@venusprotocol/governance-contracts": ^2.9.0 + "@venusprotocol/governance-contracts": ^2.13.0 "@venusprotocol/solidity-utilities": ^2.0.0 - "@venusprotocol/venus-protocol": ^9.1.0 + "@venusprotocol/venus-protocol": ^9.7.0 ethers: ^5.6.8 - hardhat: 2.19.5 + hardhat: 2.22.18 hardhat-deploy: ^0.12.4 module-alias: ^2.2.2 + patch-package: ^8.0.0 solidity-docgen: ^0.6.0-beta.29 - checksum: 7fe12e7179504bd019cad1894db51e0b3ff1fe674222fd0ef49cc8a4627d88054ab7811b7d26dfab5bbb4fc13b14cb5f1e98783094ef3602cc4eb0a6a384c8dc + checksum: c1d6a6eacedc9f6883a5a2cc85530fe5e9390ecb9cfcc0f526f09cf059ea25098c1c9e208767e74f73cd8e13ae04bb4acd6f6a43431db8686a0e75bd72794af9 languageName: node linkType: hard @@ -3385,7 +3386,7 @@ __metadata: "@typescript-eslint/eslint-plugin": ^5.40.0 "@typescript-eslint/parser": ^5.40.0 "@venusprotocol/governance-contracts": ^2.13.0 - "@venusprotocol/oracle": 2.10.0 + "@venusprotocol/oracle": 2.15.0 "@venusprotocol/protocol-reserve": ^3.4.0 "@venusprotocol/solidity-utilities": ^2.1.0 "@venusprotocol/token-bridge": ^2.7.0